const API = require("../../lib/API.js")
const Redis = require('../../plugin/DataBase/Redis')
const db = require("../../plugin/DataBase/db.js")
const { BaseStdResponse } = require("../../BaseStdResponse.js")
const AccessControl = require("../../lib/AccessControl.js")
const mq = require('../../plugin/mq')
const {
    assertRunforgeTaskIngress,
    publishRunforgeTask
} = require('../../plugin/mq/runforgeTaskMq')
const { planJkesManualRun } = require('../../plugin/jkes/monthPolicy')
const {
    markLoginExpiredByStudentNum,
    LOGIN_EXPIRED_MSG
} = require('../../plugin/jkes/syncLepaoAccountFromToken')
const { parsePaceToSecPerKm, clampManualPaceSec } = require('../../plugin/jkes/paceUtils')
const jkesRedisKeys = require('../../plugin/jkes/redisKeys')
const mqNames = require('../../plugin/mq/jkesMqNames')

class SingleRun extends API {
    constructor() {
        super()

        this.setPath('/Lepao/SingleRun')
        this.setMethod('GET')
    }

    async onRequest(req, res) {
        let { uuid, session, student_num, distance_km, pace } = req.query

        if ([uuid, session, student_num].some(value => value === '' || value === null || value === undefined))
            return res.json({
                ...BaseStdResponse.MISSING_PARAMETER
            })

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

        // let hour = new Date().getHours()
        // if (hour < 7)
        //     return res.json({
        //         ...BaseStdResponse.ERR,
        //         msg: '当前不在有效乐跑时间范围内。请在7:00~24:00发起乐跑'
        //     })

        try {
            const isProgress = await Redis.get(jkesRedisKeys.lepaoProgress(student_num))
            if (isProgress)
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: '该账号已进入乐跑任务队列，请等待乐跑完成后再进行乐跑操作'
                })

            let selectSql = 'SELECT create_user FROM lepao_account WHERE student_num = ?'
            let selectRows = await db.query(selectSql, [student_num])
            if (!selectRows || selectRows.length === 0)
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: '发起乐跑失败！未找到账户信息'
                })

            if (selectRows[0].create_user !== uuid) {
                let permission = await AccessControl.getPermission(uuid)
                if (!permission.includes("admin") && !permission.includes("service"))
                    return res.json({
                        ...BaseStdResponse.ERR,
                        msg: '发起乐跑失败！未找到账户信息'
                    })
            }

            let sql = 'SELECT token, state FROM lepao_account WHERE student_num = ?'
            let rows = await db.query(sql, [student_num])
            if (!rows || rows.length === 0)
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: '发起乐跑失败！未找到对应的账号信息'
                })

            if (rows[0].state !== 1)
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: '账号状态为未登录，请使用登录器更新账号信息后乐跑'
                })

            if ([distance_km, pace].some((v) => v === '' || v === null || v === undefined))
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: '请传入单次距离 distance_km（1–10）与配速（如 5:30）'
                })

            const dist = Number(distance_km)
            let paceSecPerKm
            try {
                paceSecPerKm = clampManualPaceSec(parsePaceToSecPerKm(pace))
            } catch (e) {
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: e.message || '配速无效'
                })
            }

            const plan = await planJkesManualRun(student_num, rows[0].token, dist)
            if (!plan.run) {
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: plan.reason || '当前无法发起单次乐跑'
                })
            }

            res.json({
                ...BaseStdResponse.OK
            })

            try {
                const channel = await mq.getChannel(mqNames.channelLepaoApi)
                await assertRunforgeTaskIngress(channel, this.logger)

                const taskId = `lepao:${Date.now()}:${student_num}`
                const payload = {
                    id: taskId,
                    type: 'lepao.startRun',
                    data: {
                        taskId,
                        account: student_num,
                        targetKm: plan.targetKm,
                        manual: true,
                        paceSecPerKm
                    },
                    retry: 0
                }

                publishRunforgeTask(channel, payload)
            } catch (err) {
                this.logger.error(`后台乐跑任务异常：${err.stack}`)
            }

        } catch (err) {
            this.logger.error(`手动乐跑失败！${err.stack}`)
            if (err?.loginExpired) {
                await markLoginExpiredByStudentNum(student_num)
                return res.json({
                    ...BaseStdResponse.ERR,
                    msg: err.message || LOGIN_EXPIRED_MSG
                })
            }
            return res.json({
                ...BaseStdResponse.ERR,
                msg: '乐跑失败！请稍后再试'
            })
        }
    }
}

module.exports.SingleRun = SingleRun
