const db = require('../plugin/DataBase/db')
const Redis = require('../plugin/DataBase/Redis')
const { releaseUsageForOrder } = require('./CouponService')
const { insertLedgerRecord } = require('./Lepao/CountLedger')

const ORDER_STATE_PENDING = 0
const ORDER_STATE_PROCESSING = 1
const ORDER_STATE_COMPLETED = 2
const ORDER_STATE_CLOSED = 3
const ORDER_STATE_ERROR = 4

function normalizeResult(result) {
    return Array.isArray(result) ? result[0] : result
}

async function closePendingOrder({ orderId, operatorUuid = null, payId = null, logger } = {}) {
    if (!orderId) return { closed: false, reason: 'missing_order_id' }

    const conn = await db.connect()
    try {
        await conn.beginTransaction()

        const [orderRows] = await conn.execute(
            'SELECT orderId, state, goods_id, create_user FROM orders WHERE orderId = ? FOR UPDATE',
            [orderId]
        )
        const order = orderRows?.[0]
        if (!order) {
            await conn.rollback()
            return { closed: false, reason: 'not_found' }
        }
        if (Number(order.state) !== ORDER_STATE_PENDING) {
            await conn.rollback()
            return { closed: false, reason: 'state_changed', state: Number(order.state) }
        }

        const params = payId
            ? [ORDER_STATE_CLOSED, payId, orderId, ORDER_STATE_PENDING]
            : [ORDER_STATE_CLOSED, orderId, ORDER_STATE_PENDING]
        const sql = payId
            ? 'UPDATE orders SET state = ?, pay_id = ? WHERE orderId = ? AND state = ?'
            : 'UPDATE orders SET state = ? WHERE orderId = ? AND state = ?'
        const [closeRes] = await conn.execute(sql, params)
        if (!closeRes || closeRes.affectedRows !== 1) {
            await conn.rollback()
            return { closed: false, reason: 'update_failed' }
        }

        if (order.goods_id != null) {
            await conn.execute('UPDATE goods SET num = num + 1 WHERE id = ?', [order.goods_id])
        }

        await conn.commit()
    } catch (error) {
        try { await conn.rollback() } catch (_) { }
        logger?.error?.(`关闭订单失败 ${orderId}: ${error.stack || error}`)
        throw error
    }

    try {
        await releaseUsageForOrder(orderId)
        await Redis.del(`payData:${orderId}`)
    } catch (cleanupError) {
        logger?.warn?.(`关闭订单后清理资源失败 ${orderId}: ${cleanupError.stack || cleanupError}`)
    }

    logger?.info?.(`订单已关闭并返还库存，订单号：${orderId}${operatorUuid ? `，操作人：${operatorUuid}` : ''}`)
    return { closed: true }
}

async function completePaidOrder({ orderId, payType, payId, payTime = Date.now(), paidAmount = null, logger } = {}) {
    if (!orderId) return { completed: false, reason: 'missing_order_id' }

    const conn = await db.connect()
    try {
        await conn.beginTransaction()

        const [lockRows] = await conn.execute(
            'SELECT orderId, state, price FROM orders WHERE orderId = ? FOR UPDATE',
            [orderId]
        )
        const locked = lockRows?.[0]
        if (!locked || Number(locked.state) !== ORDER_STATE_PENDING) {
            await conn.rollback()
            return {
                completed: false,
                reason: locked ? 'state_changed' : 'not_found',
                state: locked ? Number(locked.state) : null
            }
        }

        if (paidAmount !== null && Math.abs(Number(locked.price) - Number(paidAmount)) > 0.001) {
            await conn.rollback()
            logger?.error?.(`订单支付金额不匹配，订单号：${orderId}，应付：${locked.price}，实付：${paidAmount}`)
            return { completed: false, reason: 'amount_mismatch' }
        }

        const [markRows] = await conn.execute(
            'UPDATE orders SET state = ?, pay_type = ?, pay_id = ?, pay_time = ? WHERE orderId = ? AND state = ?',
            [ORDER_STATE_PROCESSING, payType, payId, payTime, orderId, ORDER_STATE_PENDING]
        )
        if (!markRows || markRows.affectedRows !== 1) {
            await conn.rollback()
            return { completed: false, reason: 'state_changed' }
        }

        const [orderRows] = await conn.execute(
            `SELECT
                o.create_user,
                g.lepao_count,
                g.ic_count,
                g.vip
             FROM orders o
             LEFT JOIN goods g ON o.goods_id = g.id
             WHERE o.orderId = ?
             LIMIT 1`,
            [orderId]
        )
        const order = orderRows?.[0]
        if (!order || !order.create_user) {
            await conn.execute('UPDATE orders SET state = ? WHERE orderId = ?', [ORDER_STATE_ERROR, orderId])
            await conn.commit()
            return { completed: false, reason: 'bad_order_data' }
        }

        const addLepao = Number(order.lepao_count || 0)
        const addIc = Number(order.ic_count || 0)
        const [userRows] = await conn.execute(
            'SELECT lepao_count FROM users WHERE uuid = ? FOR UPDATE',
            [order.create_user]
        )
        if (!userRows || userRows.length !== 1) {
            await conn.execute('UPDATE orders SET state = ? WHERE orderId = ?', [ORDER_STATE_ERROR, orderId])
            await conn.commit()
            return { completed: false, reason: 'user_not_found' }
        }

        const beforeLepao = Number(userRows[0].lepao_count || 0)
        const afterLepao = beforeLepao + addLepao
        const [updateUserRes] = await conn.execute(
            'UPDATE users SET lepao_count = lepao_count + ?, ic_count = ic_count + ?, vip = ? WHERE uuid = ?',
            [addLepao, addIc, order.vip, order.create_user]
        )
        if (!updateUserRes || updateUserRes.affectedRows !== 1) {
            await conn.execute('UPDATE orders SET state = ? WHERE orderId = ?', [ORDER_STATE_ERROR, orderId])
            await conn.commit()
            return { completed: false, reason: 'update_user_failed' }
        }

        const [finishRes] = await conn.execute(
            'UPDATE orders SET state = ? WHERE orderId = ? AND state = ?',
            [ORDER_STATE_COMPLETED, orderId, ORDER_STATE_PROCESSING]
        )
        if (!finishRes || finishRes.affectedRows !== 1) {
            await conn.rollback()
            return { completed: false, reason: 'finish_failed' }
        }

        if (addLepao !== 0) {
            await insertLedgerRecord({
                executor: conn,
                userUuid: order.create_user,
                delta: addLepao,
                balanceBefore: beforeLepao,
                balanceAfter: afterLepao,
                bizType: 'purchase',
                bizId: orderId,
                remark: `订单号：${orderId}`
            })
        }

        await conn.commit()

        try { await Redis.del(`payData:${orderId}`) } catch (_) { }
        logger?.info?.(`订单支付处理完成，订单号：${orderId}`)
        return { completed: true, userUuid: order.create_user, addLepao }
    } catch (error) {
        try { await conn.rollback() } catch (_) { }
        logger?.error?.(`完成订单失败 ${orderId}: ${error.stack || error}`)
        throw error
    }
}

module.exports = {
    ORDER_STATE_PENDING,
    ORDER_STATE_PROCESSING,
    ORDER_STATE_COMPLETED,
    ORDER_STATE_CLOSED,
    ORDER_STATE_ERROR,
    closePendingOrder,
    completePaidOrder,
    normalizeResult
}
