const crypto = require('crypto')
const config = require('../config.json')
const { normalizePayBaseUrl } = require('./PaymentClient')
const { getRuntimeConfig } = require('./RuntimeConfig')

const DEFAULT_PAYMENT_METHODS = [
    { type: 'alipay', name: '支付宝' },
    { type: 'wxpay', name: '微信支付' }
]

async function getPaymentMethods() {
    const paymentConfig = await getRuntimeConfig('pay', {
        required: false,
        defaultValue: { methods: DEFAULT_PAYMENT_METHODS }
    })
    const methods = paymentConfig?.methods
    if (!Array.isArray(methods) || methods.length === 0) {
        return DEFAULT_PAYMENT_METHODS
    }

    return methods
        .filter(method => method && typeof method.type === 'string' && method.type.trim())
        .map(method => ({
            type: method.type.trim(),
            name: String(method.name || method.type).trim()
        }))
}

async function isSupportedPaymentMethod(payType) {
    return (await getPaymentMethods()).some(method => method.type === payType)
}

function generatePaymentSign(params, key) {
    const query = Object.keys(params)
        .sort()
        .map(keyName => `${keyName}=${params[keyName]}`)
        .join('&') + key
    return crypto.createHash('md5').update(query, 'utf8').digest('hex')
}

async function buildPaymentSession({ orderId, gatewayOrderNo = orderId, payType, goodsName, price, deviceType }) {
    const paymentConfig = await getRuntimeConfig('pay')
    if (!paymentConfig.pid || !paymentConfig.url || !paymentConfig.key || !paymentConfig.return_url) {
        throw new Error('支付配置错误，请联系管理员')
    }
    if (!await isSupportedPaymentMethod(payType)) {
        throw new Error('不支持的支付方式')
    }

    const isUniapp = deviceType === 'RunForge Uniapp Client'
    const returnBaseUrl = isUniapp ? paymentConfig.uni_return_url : paymentConfig.return_url
    if (!returnBaseUrl) {
        throw new Error('支付返回地址配置错误，请联系管理员')
    }

    const payData = {
        pid: paymentConfig.pid,
        type: payType,
        out_trade_no: gatewayOrderNo,
        notify_url: `${config.url}/Order/CallBack`,
        return_url: `${returnBaseUrl}${orderId}`,
        name: goodsName,
        money: String(price)
    }
    payData.sign = generatePaymentSign(payData, paymentConfig.key)
    payData.sign_type = 'MD5'

    return {
        payUrl: `${normalizePayBaseUrl(paymentConfig.url)}/submit.php`,
        payData,
        // 客户端收到后应以 payData 创建并自动提交一个 POST 表单，进入支付网关。
        autoSubmit: true
    }
}

module.exports = {
    buildPaymentSession,
    getPaymentMethods,
    isSupportedPaymentMethod
}
