const db = require('../plugin/DataBase/db')
const Redis = require('../plugin/DataBase/Redis')

const CONFIG_KEYS = ['pay', 'email', 'unilogin', 'proxyForwardServer']
const CACHE_TTL_SECONDS = 300

class RuntimeConfigNotFoundError extends Error {
    constructor(key) {
        super(`未配置或未启用 ${key}`)
        this.name = 'RuntimeConfigNotFoundError'
        this.code = 'RUNTIME_CONFIG_NOT_FOUND'
        this.key = key
    }
}

function cacheKey(key) {
    return `runtimeConfig:${key}`
}

async function getRuntimeConfig(key, options = {}) {
    const { required = true, defaultValue = undefined } = options
    if (!CONFIG_KEYS.includes(key)) throw new Error('不支持的运行时配置')
    const cached = await Redis.get(cacheKey(key))
    if (cached) return JSON.parse(cached)

    const rows = await db.query(
        `SELECT config_value FROM runtime_configs
         WHERE config_key = ? AND enabled = 1
        ORDER BY is_default DESC, updated_at DESC LIMIT 1`,
        [key]
    )
    if (!rows?.[0]) {
        if (!required) return defaultValue
        throw new RuntimeConfigNotFoundError(key)
    }
    const value = typeof rows[0].config_value === 'object'
        ? rows[0].config_value
        : JSON.parse(rows[0].config_value)
    await Redis.set(cacheKey(key), JSON.stringify(value), { EX: CACHE_TTL_SECONDS })
    return value
}

async function getAllRuntimeConfigs() {
    const rows = await db.query(
        `SELECT config_key, config_name, config_value, enabled, is_default, updated_at, updated_by
         FROM runtime_configs ORDER BY config_key, is_default DESC, updated_at DESC`
    ) || []
    return rows.map(row => ({
        ...row,
        config_value: typeof row.config_value === 'object' ? row.config_value : JSON.parse(row.config_value)
    }))
}

function validateRuntimeConfig(key, value) {
    if (key === 'email') {
        if (!Array.isArray(value)) throw new Error('邮件配置必须为数组')
        return value.map((item, index) => ({ ...item, priority: Number(item.priority ?? index) }))
            .sort((a, b) => a.priority - b.priority)
    }
    if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`${key} 配置必须为对象`)
    if (key === 'pay' && (!Array.isArray(value.methods) || value.methods.some(item => !item?.type))) {
        throw new Error('付款方式配置无效')
    }
    return value
}

async function saveRuntimeConfig({ key, name = 'default', value, enabled = true, isDefault = false, updatedBy }) {
    if (!CONFIG_KEYS.includes(key)) throw new Error('不支持的运行时配置')
    const normalized = validateRuntimeConfig(key, value)
    const result = await db.query(
        `INSERT INTO runtime_configs (config_key, config_name, config_value, enabled, is_default, updated_at, updated_by)
         VALUES (?, ?, ?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE config_value = VALUES(config_value), enabled = VALUES(enabled),
         is_default = VALUES(is_default), updated_at = VALUES(updated_at), updated_by = VALUES(updated_by)`,
        [key, String(name).trim(), JSON.stringify(normalized), enabled ? 1 : 0, isDefault ? 1 : 0, Date.now(), updatedBy || null]
    )
    if (result === undefined) throw new Error('保存运行时配置失败')
    if (isDefault) {
        await db.query('UPDATE runtime_configs SET is_default = IF(config_name = ?, 1, 0) WHERE config_key = ?', [String(name).trim(), key])
    }
    await Redis.del(cacheKey(key))
    return normalized
}

async function selectRuntimeConfig({ key, name, updatedBy }) {
    if (!CONFIG_KEYS.includes(key) || !name) throw new Error('配置类型或名称无效')
    const result = await db.query(
        'UPDATE runtime_configs SET is_default = IF(config_name = ?, 1, 0), updated_at = ?, updated_by = ? WHERE config_key = ?',
        [name, Date.now(), updatedBy || null, key]
    )
    if (result === undefined) throw new Error('切换运行时配置失败')
    await Redis.del(cacheKey(key))
}

module.exports = {
    CONFIG_KEYS,
    RuntimeConfigNotFoundError,
    getRuntimeConfig,
    getAllRuntimeConfigs,
    saveRuntimeConfig,
    selectRuntimeConfig
}
