const db = require('../../plugin/DataBase/db')
const path = require('path')
const Logger = require('../Logger')
const mq = require('../../plugin/mq')
const EmailTemplate = require('../../plugin/Email/emailTemplate')

class Mcp {
    constructor() {
        this.logger = new Logger(path.join(__dirname, '../logs/MCP.log'), 'INFO')

        this.messageQueue = 'runforge_message_queue'

        this.auto_day = [
            { label: '周一', value: 1 },
            { label: '周二', value: 2 },
            { label: '周三', value: 3 },
            { label: '周四', value: 4 },
            { label: '周五', value: 5 },
            { label: '周六', value: 6 },
            { label: '周日', value: 0 }
        ]

        this.area = ["兰花湖校区跑区", "主校区北跑区", "主校区南跑区", "重庆工商大学茶园校区", "随机分配"]

        this.auto_time = [
            { label: '随机分配', value: -1 },
            ...Array.from({ length: 17 }, (_, i) => {
                const hour = i + 7
                return { label: `${hour} ~ ${hour + 1}时`, value: hour }
            })
        ]

        this.autoTimeLabel = (record) => {
            if (record.auto_time === -1) {
                if (record.today_auto_time)
                    return `随机-今日${record.today_auto_time}时`
                return '随机-待分配'
            }
            const match = this.auto_time.find(item => item.value === record.auto_time)
            return match ? match.label : '-'
        }

        this.emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
        this.banEmailList = ['icloud.com']
    }

    async bind_account({ sender, bind_code }) {
        try {
            if ([sender, bind_code].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收绑定账号请求：${sender},绑定码:${bind_code}`)
            let selectSql = 'SELECT bot_account FROM lepao_extra WHERE bot_account = ?'
            let selectRows = await db.query(selectSql, [sender])
            if (!selectRows) return '系统出错，请稍后再试'
            if (selectRows.length !== 0) return '您已绑定其他账号，请先解绑'

            let umo = `QQ2749761853:FriendMessage:${sender}`
            let sql = `
                SELECT 
                    f.student_num, a.name, f.bot_account
                FROM 
                    lepao_extra f
                LEFT JOIN 
                    lepao_account a
                ON 
                    f.student_num = a.student_num
                WHERE 
                    f.bind_code = ?
            `
            const rows = await db.query(sql, [bind_code])
            if (!rows || rows.length === 0) return '系统出错，请稍后再试'

            if (rows[0].bot_account !== null) {
                if (rows[0].bot_account !== sender) return '该账号已被他人绑定，请联系客服解绑'
                return '该账号您已绑定'
            }

            let insertSql = `
                UPDATE lepao_extra SET bot_account = ?, bot_umo = ? WHERE bind_code = ?
            `
            let insertRows = await db.query(insertSql, [sender, umo, bind_code])
            if (!insertRows || insertRows.affectedRows !== 1)
                return '系统出错，请稍后再试'
            return `绑定成功，姓名:${rows[0].name ?? '未更新，请使用乐跑登录器更新账号信息'}，学号：${rows[0].student_num}`
        } catch (error) {
            this.logger.error(`MCP绑定账号出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async get_account_info({ sender }) {
        try {
            if ([sender].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收获取账号信息请求：${sender}`)
            let sql = `
                SELECT 
                    l.name,
                    l.student_num,
                    l.state,
                    l.area,
                    l.auto_time,
                    l.total_num,
                    l.term_num,
                    l.academy_name,
                    l.sex,
                    l.grade_id,
                    l.email,
                    l.auto_run,
                    l.today_auto_time,
                    l.target_count,
                    l.auto_day,
                    l.notice_type
                FROM 
                    lepao_account l
                LEFT JOIN 
                    lepao_extra f 
                ON
                    l.student_num = f.student_num
                WHERE 
                    f.bot_account = ?
            `
            const rows = await db.query(sql, [sender])
            if (!rows || rows.length == 0) return '您尚未绑定乐跑账号，请先绑定'

            let data = rows[0]
            let returnMsg = `
                姓名:${data.name ?? '未更新，请使用乐跑登录器更新账号信息'};学号：${data.student_num};账号状态：${data.state === 1 ? '正常' : '需使用乐跑登录器更新账号信息'};乐跑跑区：${data.area == '' ? "随机分配" : data.area};自动乐跑状态：${data.auto_run === 1 ? '开启' : '关闭'}
                `
            if (data.auto_run === 1) {
                returnMsg += `自动乐跑时间：${this.autoTimeLabel(data)};`
                returnMsg += `自动乐跑星期：${data.auto_day.slice().sort((a, b) => {
                    if (a === 0) return 1; if (b === 0) return -1; return a - b;
                }).map(day => this.auto_day.find(item => item.value === day)?.label).join(',')};`
            }
            if (data.sex) returnMsg += `性别：${data.sex === 1 ? '男' : '女'};`
            if (data.email) returnMsg += `邮箱：${data.email};`
            if (data.grade) returnMsg += `邮箱：${data.grade};`
            if (data.academy_name) returnMsg += `学院：${data.academy_name};`
            if (data.grade_id) returnMsg += `年级：${data.grade_id}级;`
            if (data.target_count) returnMsg += `目标乐跑次数：${data.target_count};`
            if (data.total_num) returnMsg += `累计乐跑次数：${data.total_num};`
            if (data.notice_type) returnMsg += `通知方式：${data.notice_type};`

            return returnMsg
        } catch (error) {
            this.logger.error(`MCP查询账号信息出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async unbind_account({ sender }) {
        try {
            if ([sender].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收解绑账号请求：${sender}`)
            let insertSql = `
                UPDATE lepao_extra SET bot_account = NULL, bot_umo = NULL WHERE bot_account = ?
            `
            let insertRows = await db.query(insertSql, [sender])
            if (!insertRows || insertRows.affectedRows !== 1)
                return '系统出错，请稍后再试'
            return `解绑成功`
        } catch (error) {
            this.logger.error(`MCP解绑账号出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async change_email({ sender, email }) {
        try {
            if ([sender, email].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收更换邮箱请求：${sender}`)

            if (!this.emailRegex.test(email))
                return '请检查邮箱格式是否正确'

            const emailDomain = email.split('@')[1].toLowerCase()
            if (this.banEmailList.includes(emailDomain))
                return `暂不支持使用 ${emailDomain} 域名的邮箱，请更换其他邮箱后重试`

            let insertSql = `
                UPDATE 
                    lepao_account la
                JOIN 
                    lepao_extra le 
                ON 
                    la.student_num = le.student_num
                SET 
                    la.email = ?
                WHERE 
                    le.bot_account = ?
            `

            let insertRows = await db.query(insertSql, [email, sender])
            if (!insertRows || insertRows.affectedRows === 0)
                return '您尚未绑定乐跑账号，请先绑定'
            return `更换成功`
        } catch (error) {
            this.logger.error(`MCP更换邮箱出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async set_notification({ sender, mode }) {
        try {
            if ([sender, mode].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收设置通知请求：${sender},mode:${mode}`)
            if (mode !== 'email' && mode !== 'bot' && mode !== 'none') return '通知type不合法，仅支持 email, bot, none三种模式'

            let sql = `
                SELECT 
                    a.notice_type, a.email
                FROM 
                    lepao_extra f
                LEFT JOIN 
                    lepao_account a
                ON 
                    f.student_num = a.student_num
                WHERE 
                    f.bot_account = ?
            `
            const rows = await db.query(sql, [sender])
            if (!rows || rows.length == 0) return '您尚未绑定乐跑账号，请先绑定'

            if (!rows[0].email) return '该账号还未设置邮箱，请先使用change_email设置邮箱'
            if (rows[0].notice_type === 'mode') return `当前已是${mode}通知方式，无需修改`

            let insertSql = `
                UPDATE 
                    lepao_account la
                JOIN 
                    lepao_extra le 
                ON 
                    la.student_num = le.student_num
                SET 
                    la.notice_type = ?
                WHERE 
                    le.bot_account = ?
            `
            let insertRows = await db.query(insertSql, [mode, sender])
            if (!insertRows || insertRows.affectedRows !== 1)
                return '系统出错，请稍后再试'
            return `操作成功`
        } catch (error) {
            this.logger.error(`MCP更换通知方式出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async change_area({ sender, area }) {
        try {
            if ([sender, area].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收更换跑区请求：${sender},area:${area}`)

            if (!this.area.includes(area)) return '系统无该跑区，无法设置'

            let insertSql = `
                UPDATE 
                    lepao_account la
                JOIN 
                    lepao_extra le 
                ON 
                    la.student_num = le.student_num
                SET 
                    la.area = ?
                WHERE 
                    le.bot_account = ?
            `
            let insertRows = await db.query(insertSql, [area === "随机分配" ? '' : area, sender])
            if (!insertRows || insertRows.affectedRows === 0)
                return '您尚未绑定乐跑账号，请先绑定'

            return `操作成功`
        } catch (error) {
            this.logger.error(`MCP更换跑区出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async change_auto_time({ sender, auto_time }) {
        try {
            if ([sender, auto_time].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收设置自动乐跑时间请求：${sender},auto_time:${auto_time}`)
            if (!(Number.isInteger(auto_time) && ((auto_time >= 7 && auto_time <= 23) || auto_time === -1))) return '乐跑时间不合法，auto_time应为7~23或-1的整数'

            let sql = `
                SELECT 
                    a.auto_run, a.auto_time, a.auto_day
                FROM 
                    lepao_extra f
                LEFT JOIN 
                    lepao_account a
                ON 
                    f.student_num = a.student_num
                WHERE 
                    f.bot_account = ?
            `
            const rows = await db.query(sql, [sender])
            if (!rows || rows.length == 0) return '您尚未绑定乐跑账号，请先绑定'

            if (rows[0].auto_run !== 1) return '该账号未开启自动乐跑，请前往RunForge系统开启自动乐跑后再设置乐跑时间'
            if (rows[0].auto_time === auto_time) return `乐跑时间与现有时间一致，无需修改`

            let insertSql = `
                UPDATE 
                    lepao_account la
                JOIN 
                    lepao_extra le 
                ON 
                    la.student_num = le.student_num
                SET 
                    la.auto_time = ?
                WHERE 
                    le.bot_account = ?
            `
            let insertRows = await db.query(insertSql, [auto_time, sender])
            if (!insertRows || insertRows.affectedRows === 0)
                return '系统出错，请稍后再试'

            const data = {
                auto_time, auto_day: rows[0].auto_day
            }

            return `操作成功，现在自动乐跑时间为：${data.auto_day.slice().sort((a, b) => {
                if (a === 0) return 1; if (b === 0) return -1; return a - b;
            }).map(day => this.auto_day.find(item => item.value === day)?.label).join(',')} ${auto_time === -1 ? '随机分配时段' : `${auto_time}~${auto_time + 1}时`}`
        } catch (error) {
            this.logger.error(`MCP更换设置自动乐跑时间出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async change_auto_day({ sender, auto_day }) {
        try {
            if ([sender, auto_day].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收设置自动乐跑请求：${sender},auto_day:${auto_day}`)
            if (!Array.isArray(auto_day) || !auto_day.every(v => Number.isInteger(v) && v >= 0 && v <= 6))
                return '乐跑星期不合法，auto_day应为仅包含整数0~6的数组'

            let sql = `
                SELECT 
                    a.auto_run, a.auto_time, a.auto_day
                FROM 
                    lepao_extra f
                LEFT JOIN 
                    lepao_account a
                ON 
                    f.student_num = a.student_num
                WHERE 
                    f.bot_account = ?
            `
            const rows = await db.query(sql, [sender])
            if (!rows || rows.length == 0) return '您尚未绑定乐跑账号，请先绑定'

            if (rows[0].auto_run !== 1) return '该账号未开启自动乐跑，请前往RunForge系统开启自动乐跑后再设置乐跑时间'

            let insertSql = `
                UPDATE 
                    lepao_account la
                JOIN 
                    lepao_extra le 
                ON 
                    la.student_num = le.student_num
                SET 
                    la.auto_day = ?
                WHERE 
                    le.bot_account = ?
            `
            let insertRows = await db.query(insertSql, [JSON.stringify(auto_day), sender])
            if (!insertRows || insertRows.affectedRows === 0)
                return '系统出错，请稍后再试'

            const auto_time = rows[0].auto_time
            const data = {
                auto_time, auto_day
            }

            return `操作成功，现在自动乐跑时间为：${data.auto_day.slice().sort((a, b) => {
                if (a === 0) return 1; if (b === 0) return -1; return a - b;
            }).map(day => this.auto_day.find(item => item.value === day)?.label).join(',')} ${auto_time === -1 ? '随机分配时段' : `${auto_time}~${auto_time + 1}时`}`
        } catch (error) {
            this.logger.error(`MCP更换设置自动乐跑时间出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }

    async create_work_order({ sender, email, title, content }) {
        try {
            if ([sender, email, title, content].some(value => value === '' || value === null || value === undefined))
                return '缺少参数'

            this.logger.info(`MCP接收工单创建请求：${sender},Email:${email}`)
            if (!this.emailRegex.test(email))
                return '请检查邮箱格式是否正确'

            const emailDomain = email.split('@')[1].toLowerCase()
            if (this.banEmailList.includes(emailDomain))
                return `暂不支持使用 ${emailDomain} 域名的邮箱，请更换其他邮箱后重试`

            let selectSql = `
                SELECT 
                    l.create_user
                FROM 
                    lepao_account l
                LEFT JOIN
                    lepao_extra e
                ON 
                    l.student_num = e.student_num
                WHERE 
                    e.bot_account = ?
            `

            let selectRows = await db.query(selectSql, [sender])
            if (!selectRows || selectRows.length === 0) return '您还未绑定乐跑账号哦~请绑定后再试'

            const time = new Date().getTime()
            const uuid = selectRows[0].create_user

            let msg = []
            let message = {
                time,
                content,
                files: [],
                uuid,
                type: 'user'
            }
            msg.push(message)
            const systemMsg = {
                time,
                content: `该问题由用户${sender}通过小妍助理自动生成并提交~我们会尽快处理，请耐心等待`,
                uuid: 'e4fe0277-0b1a-41a1-b25f-8b6e4cec3281',
                type: 'system'
            }
            msg.push(systemMsg)
            let sql = 'INSERT INTO work_order (title, email, msg, create_user, create_time, update_time) VALUES (?, ?, ?, ?, ?, ?)'
            let r = await db.query(sql, [title, email, msg, uuid, time, time])

            if (!r || r.affectedRows !== 1)
                return '系统出错，请稍后再试'

            let kefuSql = `
                    SELECT email FROM users
                    WHERE JSON_CONTAINS(permission, '"admin"') OR JSON_CONTAINS(permission, '"service"')
                `

            let kefuRows = await db.query(kefuSql);

            let emails = [...new Set(kefuRows.map(row => row.email))]

            for (const email of emails) {
                if (!email) break
                EmailTemplate.orderNewReply(email, { id: r.insertId || id, content, files: [] })
            }

            return `提交成功`
        } catch (error) {
            this.logger.error(`MCP工单创建出错：${error.stack}`)
            return '系统出错，请稍后再试'
        }
    }
}

const MCP = new Mcp()
module.exports.MCP = MCP