const API = require('../../../lib/API.js')
const db = require('../../../plugin/DataBase/db.js')
const { BaseStdResponse } = require('../../../BaseStdResponse.js')
const AccessControl = require('../../../lib/AccessControl.js')
function parseUsernames(text) {
    if (!text) return []
    return [...new Set(
        String(text)
            .split(/[,，\n\r\s]+/)
            .map((s) => s.trim())
            .filter(Boolean)
    )]
}

class SaveCoupon extends API {
    constructor() {
        super()
        this.setPath('/Admin/Coupon/Save')
        this.setMethod('POST')
    }

    async onRequest(req, res) {
        const {
            uuid,
            session,
            id,
            code,
            name,
            discount_type,
            discount_value,
            user_scope,
            goods_scope,
            total_limit,
            per_user_limit,
            min_amount,
            start_time,
            end_time,
            state,
            allowed_usernames,
            allowed_goods_ids
        } = req.body

        if ([uuid, session, code, discount_type, discount_value, user_scope, goods_scope, state].some(
            (v) => v === '' || v == null
        )) {
            return res.json({ ...BaseStdResponse.MISSING_PARAMETER })
        }

        if (!(await AccessControl.checkSession(uuid, session))) {
            return res.status(401).json({ ...BaseStdResponse.ACCESS_DENIED })
        }

        const permission = await AccessControl.getPermission(uuid)
        if (!permission.includes('admin') && !permission.includes('product')) {
            return res.json({ ...BaseStdResponse.PERMISSION_DENIED })
        }

        const normalizedCode = String(code).trim().toUpperCase()
        if (!/^[A-Z0-9_-]{3,32}$/.test(normalizedCode)) {
            return res.json({
                ...BaseStdResponse.ERR,
                msg: '优惠码仅支持 3-32 位字母、数字、下划线或横线'
            })
        }

        if (!['percent', 'fixed'].includes(discount_type)) {
            return res.json({ ...BaseStdResponse.ERR, msg: '折扣类型无效' })
        }

        const dValue = Number(discount_value)
        if (discount_type === 'percent' && (dValue <= 0 || dValue > 100)) {
            return res.json({ ...BaseStdResponse.ERR, msg: '折扣比例需在 1～100 之间' })
        }
        if (discount_type === 'fixed' && dValue <= 0) {
            return res.json({ ...BaseStdResponse.ERR, msg: '减免金额需大于 0' })
        }

        const uScope = Number(user_scope)
        const gScope = Number(goods_scope)
        const usernames = parseUsernames(allowed_usernames)
        const goodsIds = (Array.isArray(allowed_goods_ids) ? allowed_goods_ids : [])
            .map((g) => Number(g))
            .filter((g) => g > 0)

        if (uScope === 1 && usernames.length === 0) {
            return res.json({ ...BaseStdResponse.ERR, msg: '请指定可使用该优惠码的用户' })
        }
        if (gScope === 1 && goodsIds.length === 0) {
            return res.json({ ...BaseStdResponse.ERR, msg: '请指定可使用该优惠码的商品' })
        }

        const dup = await db.query(
            'SELECT id FROM coupons WHERE code = ? AND id != ? LIMIT 1',
            [normalizedCode, id || 0]
        )
        if (dup && dup.length > 0) {
            return res.json({ ...BaseStdResponse.ERR, msg: '优惠码已存在' })
        }

        const time = Date.now()
        const conn = await db.connect()

        try {
            await conn.beginTransaction()

            let couponId = id ? Number(id) : null

            if (!couponId) {
                const [ins] = await conn.execute(
                    `INSERT INTO coupons (
                        code, name, discount_type, discount_value, user_scope, goods_scope,
                        total_limit, per_user_limit, min_amount, start_time, end_time,
                        state, create_user, create_time, update_time
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
                    [
                        normalizedCode,
                        name || '',
                        discount_type,
                        dValue,
                        uScope,
                        gScope,
                        Number(total_limit || 0),
                        Math.max(1, Number(per_user_limit || 1)),
                        Number(min_amount || 0),
                        start_time || null,
                        end_time || null,
                        Number(state),
                        uuid,
                        time,
                        time
                    ]
                )
                couponId = ins.insertId
            } else {
                await conn.execute(
                    `UPDATE coupons SET
                        code = ?, name = ?, discount_type = ?, discount_value = ?,
                        user_scope = ?, goods_scope = ?, total_limit = ?, per_user_limit = ?,
                        min_amount = ?, start_time = ?, end_time = ?, state = ?, update_time = ?
                     WHERE id = ?`,
                    [
                        normalizedCode,
                        name || '',
                        discount_type,
                        dValue,
                        uScope,
                        gScope,
                        Number(total_limit || 0),
                        Math.max(1, Number(per_user_limit || 1)),
                        Number(min_amount || 0),
                        start_time || null,
                        end_time || null,
                        Number(state),
                        time,
                        couponId
                    ]
                )
            }

            await conn.execute('DELETE FROM coupon_users WHERE coupon_id = ?', [couponId])
            await conn.execute('DELETE FROM coupon_goods WHERE coupon_id = ?', [couponId])

            if (uScope === 1) {
                for (const username of usernames) {
                    const [userRows] = await conn.execute(
                        'SELECT uuid FROM users WHERE username = ? LIMIT 1',
                        [username]
                    )
                    if (!userRows || userRows.length !== 1) {
                        await conn.rollback()
                        return res.json({
                            ...BaseStdResponse.ERR,
                            msg: `用户不存在：${username}`
                        })
                    }
                    await conn.execute(
                        'INSERT INTO coupon_users (coupon_id, user_uuid) VALUES (?, ?)',
                        [couponId, userRows[0].uuid]
                    )
                }
            }

            if (gScope === 1) {
                for (const goodsId of goodsIds) {
                    await conn.execute(
                        'INSERT INTO coupon_goods (coupon_id, goods_id) VALUES (?, ?)',
                        [couponId, goodsId]
                    )
                }
            }

            await conn.commit()
            return res.json({ ...BaseStdResponse.OK, id: couponId })
        } catch (err) {
            await conn.rollback()
            this.logger.error(`保存优惠码失败: ${err.stack}`)
            return res.json({ ...BaseStdResponse.ERR, msg: '保存优惠码失败' })
        }
    }
}

module.exports.SaveCoupon = SaveCoupon
