const API = require("../../lib/API");
const db = require('../../plugin/DataBase/db')
const mq = require('../../plugin/mq')
const { assertRunforgeTaskIngress, publishRunforgeTask } = require('../../plugin/mq/runforgeTaskMq')
const { scheduleDelayedRunforgeTask } = require('../../plugin/mq/lepaoAutoScheduleRedis')
const mqNames = require('../../plugin/mq/jkesMqNames')

const { BaseStdResponse } = require("../../BaseStdResponse");
const { prepareAutoRunTask, buildStartRunPayload } = require('../../plugin/jkes/prepareAutoRunTask')

class StartAutoLepao extends API {
    constructor() {
        super();

        this.noEncrypt()
        this.setPath('/Corn/StartAutoLepao');
        this.setMethod('GET');
    }

    async publishAutoRun(channel, item, payload, logLabel) {
        const { name, student_num } = item
        try {
            publishRunforgeTask(channel, payload)
            this.logger.info(`${name}(${student_num})${logLabel}`)
        } catch (err) {
            this.logger.error(`${name}(${student_num})乐跑投递失败：${err.message || err}`)
        }
    }

    async onRequest(req, res) {
        try {
            res.json({
                ...BaseStdResponse.OK
            })

            const day = new Date().getDay()
            const hour = new Date().getHours()
            this.logger.info('开始执行自动乐跑任务')
            let sql = `
                        SELECT name, student_num, auto_day, token, target_count,
                               auto_run_distance_min_km, auto_run_distance_max_km, pace_min_sec_per_km, pace_max_sec_per_km
                        FROM lepao_account
                        WHERE auto_run = 1 AND state = 1
                            AND (auto_time = ? OR (auto_time = -1 AND today_auto_time = ?))
                            AND JSON_CONTAINS(auto_day, CAST(? AS JSON))
                        `
            let r = await db.query(sql, [hour, hour, day])
            if (!r)
                return this.logger.error('获取自动乐跑账号失败！')

            const nowMs = Date.now()
            const hourEnd = new Date()
            hourEnd.setHours(hourEnd.getHours() + 1, 0, 0, 0)
            const spreadWindowMs = Math.max(0, hourEnd.getTime() - nowMs)

            let channel
            try {
                channel = await mq.getChannel(mqNames.channelLepaoCorn)
                await assertRunforgeTaskIngress(channel, this.logger)
            } catch (err) {
                this.logger.error(`自动乐跑：连接 MQ 或声明拓扑失败：${err.message || err}`)
                return
            }

            for (const item of r) {
                const { name, student_num } = item
                const prepared = await prepareAutoRunTask(item)
                if (!prepared.run) {
                    this.logger.info(`${name}(${student_num}) JKES 自动乐跑跳过：${prepared.reason}`)
                    continue
                }

                const delayMs = spreadWindowMs > 0 ? Math.floor(Math.random() * spreadWindowMs) : 0
                const fireAt = nowMs + delayMs
                const payload = buildStartRunPayload(student_num, prepared.task, {
                    taskId: `lepao:auto:${fireAt}:${student_num}`
                })

                if (delayMs > 0) {
                    try {
                        await scheduleDelayedRunforgeTask(fireAt, payload, {
                            name,
                            account: student_num,
                            delayMs
                        })
                        this.logger.info(
                            `${name}(${student_num})已写入 Redis 调度（约 ${Math.round(delayMs / 1000)}s 后进 MQ）`
                        )
                    } catch (err) {
                        this.logger.error(`${name}(${student_num})Redis 调度失败，改为立即投递：${err.message || err}`)
                        await this.publishAutoRun(channel, item, payload, 'Redis 调度失败后已立即投递自动乐跑任务')
                    }
                    continue
                }

                await this.publishAutoRun(channel, item, payload, '已投递自动乐跑任务')
            }
        } catch (error) {
            this.logger.error(error)
        }
    }
}

module.exports.StartAutoLepao = StartAutoLepao;
