const logger = require(`${__hooks}/bai_api_pb_hooks/bai_api_shared/utils/logger.js`)
const { createAppError } = require(`${__hooks}/bai_api_pb_hooks/bai_api_shared/utils/appError.js`)
const documentService = require(`${__hooks}/bai_api_pb_hooks/bai_api_shared/services/documentService.js`)

function buildBusinessId(prefix) {
    return prefix + '-' + new Date().getTime() + '-' + $security.randomString(6)
}

function normalizeText(value) {
    return String(value || '').replace(/^\s+|\s+$/g, '')
}

function normalizeOptionalNumberValue(value, fieldName) {
    if (value === '' || value === null || typeof value === 'undefined') {
        return null
    }

    const num = Number(value)
    if (!Number.isFinite(num)) {
        throw createAppError(400, fieldName + ' 必须为数字')
    }

    return num
}

function normalizeSortValue(value) {
    if (value === '' || value === null || typeof value === 'undefined') {
        return 0
    }

    const num = Number(value)
    if (!Number.isFinite(num)) {
        throw createAppError(400, 'prod_list_sort 必须为数字')
    }

    return Math.floor(num)
}

function normalizePipeValues(value) {
    return String(value || '')
        .split('|')
        .map(function (item) {
            return normalizeText(item)
        })
        .filter(function (item) {
            return !!item
        })
}

function joinUniquePipeValues(value) {
    const source = Array.isArray(value) ? value : normalizePipeValues(value)
    const result = []

    for (let i = 0; i < source.length; i += 1) {
        const current = normalizeText(source[i])
        if (!current || result.indexOf(current) !== -1) {
            continue
        }
        result.push(current)
    }

    return result.join('|')
}

function normalizeRequiredCategory(value) {
    const values = normalizePipeValues(value)
    if (!values.length) {
        throw createAppError(400, 'prod_list_category 为必填项')
    }
    return values[0]
}

function buildCategoryRankMap(records) {
    const grouped = {}
    for (let i = 0; i < records.length; i += 1) {
        const category = normalizeText(records[i].prod_list_category)
        if (!category) {
            continue
        }
        if (!grouped[category]) {
            grouped[category] = []
        }
        grouped[category].push(records[i])
    }

    const rankMap = {}
    const categories = Object.keys(grouped)
    for (let i = 0; i < categories.length; i += 1) {
        const category = categories[i]
        const items = grouped[category]
        items.sort(function (a, b) {
            const sortDiff = Number(a.prod_list_sort || 0) - Number(b.prod_list_sort || 0)
            if (sortDiff !== 0) {
                return sortDiff
            }

            const updateDiff = String(b.updated || '').localeCompare(String(a.updated || ''))
            if (updateDiff !== 0) {
                return updateDiff
            }

            return String(a.prod_list_id || '').localeCompare(String(b.prod_list_id || ''))
        })

        for (let j = 0; j < items.length; j += 1) {
            rankMap[items[j].prod_list_id] = j + 1
        }
    }

    return rankMap
}

function normalizeParameters(value) {
    if (value === null || typeof value === 'undefined' || value === '') {
        return []
    }

    const result = []
    const indexByName = {}

    function upsert(nameValue, rawValue) {
        const name = normalizeText(nameValue)
        if (!name) {
            return
        }

        const normalizedValue = rawValue === null || typeof rawValue === 'undefined' ? '' : String(rawValue)
        const existingIndex = indexByName[name]
        if (typeof existingIndex === 'number') {
            result[existingIndex].value = normalizedValue
            return
        }

        indexByName[name] = result.length
        result.push({
            name: name,
            value: normalizedValue,
        })
    }

    if (Array.isArray(value)) {
        for (let i = 0; i < value.length; i += 1) {
            const item = value[i] && typeof value[i] === 'object' ? value[i] : null
            if (!item) {
                continue
            }
            upsert(item.name || item.key, item.value)
        }
        return result
    }

    if (typeof value !== 'object') {
        throw createAppError(400, 'prod_list_parameters 必须是数组或对象')
    }

    const keys = Object.keys(value)
    for (let i = 0; i < keys.length; i += 1) {
        upsert(keys[i], value[keys[i]])
    }

    return result
}

function normalizeParametersForOutput(value) {
    if (value === null || typeof value === 'undefined' || value === '') {
        return []
    }

    let source = value
    if (typeof source === 'string') {
        try {
            source = JSON.parse(source)
        } catch (_error) {
            const raw = normalizeText(source)
            if (raw.indexOf('map[') === 0 && raw.endsWith(']')) {
                const body = raw.slice(4, -1).trim()
                if (!body) {
                    return []
                }
                const result = []
                const indexByName = {}
                const pairs = body.split(/\s+/)
                for (let i = 0; i < pairs.length; i += 1) {
                    const pair = pairs[i]
                    const separatorIndex = pair.indexOf(':')
                    if (separatorIndex <= 0) {
                        continue
                    }
                    const key = normalizeText(pair.slice(0, separatorIndex))
                    if (!key) {
                        continue
                    }
                    const val = pair.slice(separatorIndex + 1)
                    const normalizedValue = val === null || typeof val === 'undefined' ? '' : String(val)
                    const existingIndex = indexByName[key]
                    if (typeof existingIndex === 'number') {
                        result[existingIndex].value = normalizedValue
                    } else {
                        indexByName[key] = result.length
                        result.push({ name: key, value: normalizedValue })
                    }
                }
                return result
            }
            return []
        }
    }

    if (Array.isArray(source)) {
        const mapped = []
        const indexByName = {}
        for (let i = 0; i < source.length; i += 1) {
            const item = source[i] && typeof source[i] === 'object' ? source[i] : null
            if (!item) {
                continue
            }
            const name = normalizeText(item.name || item.key)
            if (!name) {
                continue
            }
            const normalizedValue = item.value === null || typeof item.value === 'undefined' ? '' : String(item.value)
            const existingIndex = indexByName[name]
            if (typeof existingIndex === 'number') {
                mapped[existingIndex].value = normalizedValue
            } else {
                indexByName[name] = mapped.length
                mapped.push({ name: name, value: normalizedValue })
            }
        }
        return mapped
    }

    if (typeof source !== 'object') {
        return []
    }

    // Some PocketBase/Goja map-like values are not directly enumerable; roundtrip to plain object.
    try {
        source = JSON.parse(JSON.stringify(source))
    } catch (_error) {}

    const result = []
    const indexByName = {}
    const keys = Object.keys(source)
    for (let i = 0; i < keys.length; i += 1) {
        const name = normalizeText(keys[i])
        if (!name) {
            continue
        }
        const current = source[keys[i]]
        const normalizedValue = current === null || typeof current === 'undefined' ? '' : String(current)
        const existingIndex = indexByName[name]
        if (typeof existingIndex === 'number') {
            result[existingIndex].value = normalizedValue
        } else {
            indexByName[name] = result.length
            result.push({ name: name, value: normalizedValue })
        }
    }

    return result
}

function ensureAttachmentExists(attachmentId, fieldName) {
    const value = normalizeText(attachmentId)
    if (!value) {
        return
    }

    try {
        documentService.getAttachmentDetail(value)
    } catch (_err) {
        throw createAppError(400, fieldName + ' 对应附件不存在：' + value)
    }
}

function findProductRecordByBusinessId(productId) {
    const records = $app.findRecordsByFilter('tbl_product_list', 'prod_list_id = {:productId}', '', 1, 0, {
        productId: productId,
    })

    return records.length ? records[0] : null
}

function exportProductRecord(record, extra) {
    const iconId = record.getString('prod_list_icon')
    let iconAttachment = null

    if (iconId) {
        try {
            iconAttachment = documentService.getAttachmentDetail(iconId)
        } catch (_error) {
            iconAttachment = null
        }
    }

    const parametersText = normalizeText(record.getString('prod_list_parameters'))
    const parametersFromText = parametersText ? normalizeParametersForOutput(parametersText) : {}
    const parametersRaw = record.get('prod_list_parameters')
    const parametersFromRaw = normalizeParametersForOutput(parametersRaw)
    const parameters = parametersFromText.length ? parametersFromText : parametersFromRaw

    return {
        pb_id: record.id,
        prod_list_id: record.getString('prod_list_id'),
        prod_list_name: record.getString('prod_list_name'),
        prod_list_modelnumber: record.getString('prod_list_modelnumber'),
        prod_list_icon: iconId,
        prod_list_icon_attachment: iconAttachment,
        prod_list_icon_url: iconAttachment ? iconAttachment.attachments_url : '',
        prod_list_description: record.getString('prod_list_description'),
        prod_list_feature: record.getString('prod_list_feature'),
        prod_list_parameters: parameters,
        prod_list_plantype: record.getString('prod_list_plantype'),
        prod_list_category: record.getString('prod_list_category'),
        prod_list_sort: Number(record.get('prod_list_sort') || 0),
        prod_list_category_rank: extra && extra.categoryRank ? Number(extra.categoryRank) : 0,
        prod_list_comm_type: record.getString('prod_list_comm_type'),
        prod_list_series: record.getString('prod_list_series'),
        prod_list_power_supply: record.getString('prod_list_power_supply'),
        prod_list_tags: record.getString('prod_list_tags'),
        prod_list_basic_price: record.get('prod_list_basic_price'),
        prod_list_status: record.getString('prod_list_status'),
        prod_list_remark: record.getString('prod_list_remark'),
        created: String(record.created || ''),
        updated: String(record.updated || ''),
    }
}

function listProducts(payload) {
    const allRecords = $app.findRecordsByFilter('tbl_product_list', '', '', 500, 0)
    const keyword = normalizeText(payload.keyword).toLowerCase()
    const status = normalizeText(payload.status)
    const category = normalizeText(payload.prod_list_category)
    const result = []

    const allItems = []
    for (let i = 0; i < allRecords.length; i += 1) {
        allItems.push(exportProductRecord(allRecords[i]))
    }

    const rankMap = buildCategoryRankMap(allItems)

    for (let i = 0; i < allItems.length; i += 1) {
        const source = allItems[i]
        const item = Object.assign({}, source, {
            prod_list_category_rank: rankMap[source.prod_list_id] || 0,
        })
        const matchedKeyword = !keyword
            || item.prod_list_id.toLowerCase().indexOf(keyword) !== -1
            || item.prod_list_name.toLowerCase().indexOf(keyword) !== -1
            || item.prod_list_modelnumber.toLowerCase().indexOf(keyword) !== -1
            || item.prod_list_tags.toLowerCase().indexOf(keyword) !== -1
        const matchedStatus = !status || item.prod_list_status === status
        const matchedCategory = !category || item.prod_list_category === category

        if (matchedKeyword && matchedStatus && matchedCategory) {
            result.push(item)
        }
    }

    result.sort(function (a, b) {
        return String(b.updated || '').localeCompare(String(a.updated || ''))
    })

    return result
}

function getProductDetail(productId) {
    const record = findProductRecordByBusinessId(productId)
    if (!record) {
        throw createAppError(404, '未找到对应产品')
    }

    const allRecords = $app.findRecordsByFilter('tbl_product_list', '', '', 500, 0)
    const allItems = []
    for (let i = 0; i < allRecords.length; i += 1) {
        allItems.push(exportProductRecord(allRecords[i]))
    }
    const rankMap = buildCategoryRankMap(allItems)

    return exportProductRecord(record, {
        categoryRank: rankMap[record.getString('prod_list_id')] || 0,
    })
}

function createProduct(_userOpenid, payload) {
    const targetProductId = normalizeText(payload.prod_list_id) || buildBusinessId('PROD')
    const duplicated = findProductRecordByBusinessId(targetProductId)
    if (duplicated) {
        throw createAppError(400, 'prod_list_id 已存在')
    }

    ensureAttachmentExists(payload.prod_list_icon, 'prod_list_icon')

    const collection = $app.findCollectionByNameOrId('tbl_product_list')
    const record = new Record(collection)

    record.set('prod_list_id', targetProductId)
    record.set('prod_list_name', normalizeText(payload.prod_list_name))
    record.set('prod_list_modelnumber', normalizeText(payload.prod_list_modelnumber))
    record.set('prod_list_icon', normalizeText(payload.prod_list_icon))
    record.set('prod_list_description', normalizeText(payload.prod_list_description))
    record.set('prod_list_feature', normalizeText(payload.prod_list_feature))
    record.set('prod_list_parameters', normalizeParameters(payload.prod_list_parameters))
    record.set('prod_list_plantype', normalizeText(payload.prod_list_plantype))
    record.set('prod_list_category', normalizeRequiredCategory(payload.prod_list_category))
    record.set('prod_list_sort', normalizeSortValue(payload.prod_list_sort))
    record.set('prod_list_comm_type', normalizeText(payload.prod_list_comm_type))
    record.set('prod_list_series', normalizeText(payload.prod_list_series))
    record.set('prod_list_power_supply', normalizeText(payload.prod_list_power_supply))
    record.set('prod_list_tags', joinUniquePipeValues(payload.prod_list_tags))
    record.set('prod_list_status', normalizeText(payload.prod_list_status))
    record.set('prod_list_basic_price', normalizeOptionalNumberValue(payload.prod_list_basic_price, 'prod_list_basic_price'))
    record.set('prod_list_remark', normalizeText(payload.prod_list_remark))

    try {
        $app.save(record)
    } catch (err) {
        throw createAppError(400, '新增产品失败', {
            originalMessage: (err && err.message) || '未知错误',
            originalData: (err && err.data) || {},
        })
    }

    logger.info('产品创建成功', {
        prod_list_id: record.getString('prod_list_id'),
    })

    const rankMap = buildCategoryRankMap(listProducts({}))
    return exportProductRecord(record, {
        categoryRank: rankMap[record.getString('prod_list_id')] || 0,
    })
}

function updateProduct(_userOpenid, payload) {
    const targetId = normalizeText(payload.prod_list_id)
    if (!targetId) {
        throw createAppError(400, 'prod_list_id 为必填项')
    }

    const record = findProductRecordByBusinessId(targetId)
    if (!record) {
        throw createAppError(404, '未找到待修改的产品')
    }

    ensureAttachmentExists(payload.prod_list_icon, 'prod_list_icon')

    record.set('prod_list_name', normalizeText(payload.prod_list_name))
    record.set('prod_list_modelnumber', normalizeText(payload.prod_list_modelnumber))
    record.set('prod_list_icon', normalizeText(payload.prod_list_icon))
    record.set('prod_list_description', normalizeText(payload.prod_list_description))
    record.set('prod_list_feature', normalizeText(payload.prod_list_feature))
    record.set('prod_list_parameters', normalizeParameters(payload.prod_list_parameters))
    record.set('prod_list_plantype', normalizeText(payload.prod_list_plantype))
    record.set('prod_list_category', normalizeRequiredCategory(payload.prod_list_category))
    record.set('prod_list_sort', normalizeSortValue(payload.prod_list_sort))
    record.set('prod_list_comm_type', normalizeText(payload.prod_list_comm_type))
    record.set('prod_list_series', normalizeText(payload.prod_list_series))
    record.set('prod_list_power_supply', normalizeText(payload.prod_list_power_supply))
    record.set('prod_list_tags', joinUniquePipeValues(payload.prod_list_tags))
    record.set('prod_list_status', normalizeText(payload.prod_list_status))
    record.set('prod_list_basic_price', normalizeOptionalNumberValue(payload.prod_list_basic_price, 'prod_list_basic_price'))
    record.set('prod_list_remark', normalizeText(payload.prod_list_remark))

    try {
        $app.save(record)
    } catch (err) {
        throw createAppError(400, '更新产品失败', {
            originalMessage: (err && err.message) || '未知错误',
            originalData: (err && err.data) || {},
        })
    }

    logger.info('产品更新成功', {
        prod_list_id: targetId,
    })

    const rankMap = buildCategoryRankMap(listProducts({}))
    return exportProductRecord(record, {
        categoryRank: rankMap[record.getString('prod_list_id')] || 0,
    })
}

function deleteProduct(_userOpenid, productId) {
    const targetId = normalizeText(productId)
    if (!targetId) {
        throw createAppError(400, 'prod_list_id 为必填项')
    }

    const record = findProductRecordByBusinessId(targetId)
    if (!record) {
        throw createAppError(404, '未找到待删除的产品')
    }

    try {
        $app.delete(record)
    } catch (err) {
        throw createAppError(400, '删除产品失败', {
            originalMessage: (err && err.message) || '未知错误',
            originalData: (err && err.data) || {},
        })
    }

    logger.info('产品删除成功', {
        prod_list_id: targetId,
    })

    return {
        prod_list_id: targetId,
    }
}

module.exports = {
    listProducts,
    getProductDetail,
    createProduct,
    updateProduct,
    deleteProduct,
}
