import {ApiCall} from 'tsrpc';
import {ReqAddHuoDong} from '../../monopoly/protocols/PtlAddHuoDong';
import {ActionLog} from '../../public/actionLog/actionLog';
import {HuoDongFun} from '../../public/huodongfun';
import {PataFun} from '../../public/pata';
import {PayFun} from '../../public/pay';
import {ZhanLingTasks} from '../../public/zhanling';
import {jijinType} from '../../shared/protocols/event/jijin/PtlOpen';
import {hongdianKey, hongdianVal} from '../../shared/protocols/hongdian/PtlGet';
import {payLog} from '../../shared/protocols/pay/PtlGetList';
import {PublicShared} from '../../shared/public/public';
import {clslDb} from '../conglinshoulie/ApiOpen';
import {getVal} from '../event/jijin/ApiOpen';
import {getTaskVal} from '../event/kaifukuanghuan/ApiOpen';
import {YangChengMuBiaofun} from '../event/yangchengmubiao/fun';
import {checkIsOpen} from '../hbzb/jfs/ApiOpen';
import {PlayerShared} from "../../shared/public/player";
import {kbzzUserDb} from '../kbzz/ApiOpen';
import {PlayerFun} from "../../public/player";
import kfjsFun from "../../public/kaifujingsai";
import {RankKfjs} from "../../public/rank/rank_kfjs";
import {ShopFun} from "../../public/shop";
import {Christmasfun} from '../event/christmas/fun';

export class HongDianFun {
    /**黑榜争霸红点 */
    static async hbzBgetHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };
        if (!checkIsOpen()) return _res;
        let data = await G.mongodb.cPlayerInfo('hbzb').findOne({uid: call.uid, type: 'hbzb'});
        let _mydata = (data && data.data && data.data.refreshTime >= PublicShared.getToDayZeroTime()) ? data.data : {
            winNum: 0,
            buyFightNum: 0,
            useFightNum: 0,
            refreshTime: G.time,
            winRecPrize: [],
            useRefreshNum: 0
        };
        if (_mydata.useFightNum < _mydata.buyFightNum + G.gc.hbzb.jfsFightNum) {
            _res.show = true;
        }
        if (!_res.show) {
            let _con = JSON.parse(JSON.stringify(G.gc.hbzb.jfsFightWinNumPrize));
            for (let index = 0; index < _con.length; index++) {
                const element = _con[index];
                if (_mydata.winRecPrize.includes(index)) continue;
                if (_mydata.winNum < element.total) continue;
                _res.show = true;
                break;
            }
        }
        return _res;
    }

    /**丛林狩猎红点 */
    static async clslgetHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };
        let weekZeroTime = PublicShared.getToWeekMondayZeroTime();
        if (G.time < weekZeroTime + G.gc.clsl_com.fightTime[0] || G.time > weekZeroTime + G.gc.clsl_com.fightTime[1]) return _res;
        let _mydata = await clslDb().findOne({uid: call.uid, type: 'clsl'});
        let useNum = _mydata?.useFightNum || 0;
        let buyNum = _mydata?.buyFightNum || 0;
        if (useNum < buyNum + G.gc.clsl_com.fightNum) {
            _res.show = true;
        }

        if (!_res.show) {
            let fightWinNum = _mydata?.fightWinNum || 0;
            let _con = JSON.parse(JSON.stringify(G.gc.clsl_com.fightWinPrize));
            for (let index = 0; index < _con.length; index++) {
                const element = _con[index];
                if (_mydata?.recWinPrize?.includes(index)) continue;
                if (fightWinNum < element.total) continue;
                _res.show = true;
                break;
            }
        }
        return _res;
    }

    /**
     * 每日试炼 物资筹集 红点
     * types.money 休闲区
     * types.exp 物资部
     * types.qhs 加工仓库
     * _mydata.data.numInfo.[type].['0'] 下标‘0’原本是根据难度设定次数，改为次数共享后，取‘0’值统一计算次数
     **/
    static async mrslGetHongDian(call: ApiCall) {
        let _res = {
            show: false
        };
        let _mydata = await G.mongodb.cPlayerInfo('meirishilian').findOne({uid: call.uid, type: 'meirishilian'});
        let types = ['money', 'exp', 'qhs'];
        for (let type of types) {
            let buyNum = _mydata?.data?.numInfo?.[type]?.['0']?.buyFightNum || 0;
            let useNum = _mydata?.data?.numInfo?.[type]?.['0']?.useFightNum || 0;
            _res.show = useNum < buyNum + (PlayerShared.getMingDaoBuff(call.conn.gud, 'wzsj_free') || 0) + G.gc.meirishilian_com.fightNum
            if (_res.show) break
        }
        return _res;
    }

    /**势力争夺 红点 */
    static async slzdGetHongDian(call: ApiCall) {
        let _res = {
            show: false
        };
        let db = await G.mongodb.collection('slzdUser').findOne({uid: call.uid});

        let _mydata = (db && db.data && db.data.refreshTime >= PublicShared.getToDayZeroTime()) ? db.data : {
            fightNum: G.gc.slzd.ctorFightNum,
            winNum: 0,
            winRec: []
        };
        if (_mydata.fightNum >= 1) {
            _res.show = true;
        }

        if (!_res.show) {
            let _con = JSON.parse(JSON.stringify(G.gc.slzd.fightWinNumPrize));
            for (let index = 0; index < _con.length; index++) {
                const element = _con[index];
                if (_mydata.winRec.includes(index)) continue;
                if (_mydata.winNum < element.total) continue;
                _res.show = true;
                break;
            }
        }
        return _res;
    }

    /**清缴真主党 红点 */
    static async qjzzdGetHongDian(call: ApiCall) {
        let _res = {
            show: false
        };
        return _res
        let data = await G.mongodb.collection('scheduler').findOne({type: 'qjzzd'});
        if (!data) return _res;   // 功能未开放
        let db = await G.mongodb.cPlayerInfo('qjzzd').findOne({uid: call.uid, type: 'qjzzd'});

        let myData = (db && db.refreshTime >= data.lastRunTime) ? db : {
            refreshTime: data.lastRunTime,
            useFightNum: 0,
            maxDps: 0
        };
        if (myData.useFightNum < G.gc.qjzzd.fightNum) {
            _res.show = true;
        }
        return _res;
    }

    /**恐怖战争 红点 */
    static async kongbuzzHongDian(call: ApiCall) {
        let _res = {
            show: false
        };
        let second = G.time - PublicShared.getToWeekMondayZeroTime();
        if (second >= G.gc.kbzz.time.apply[0] && second < G.gc.kbzz.time.apply[1]) {
            // 报名时间
            let state = await G.mongodb.cPlayerInfo('kbzzApply').findOne({uid: call.uid, type: 'kbzzApply'});
            let apply = state?.apply || false;
            if (!apply) {
                _res.show = true;
                return _res;
            }
        } else {
            let dbData = await kbzzUserDb().findOne({uid: call.uid, type: 'kbzzUser'});
            let myData = dbData ? dbData : {
                score: G.gc.kbzz.playerScore,
                recScorePrize: [],
                toDayScore: 0,
                fightNum: G.gc.kbzz.fightNum
            };
            let conf = G.gc.kbzz.scorePrize;
            for (let index = 0; index < conf.length; index++) {
                const element = conf[index];
                if (myData.recScorePrize.includes(index)) continue;
                if (myData.toDayScore < element.total) continue;
                _res.show = true;
                break;
            }
        }
        return _res;
    }

    /**斩草除根（爬塔） 红点 */
    static async pataHongDian(call: ApiCall) {
        let _res = {
            show: false,
            val: {
                shopItems: {
                    show: false
                },
                saodang: {
                    show: false
                },
                reward: {
                    show: false
                }
            }
        };
        let _conf = G.gc.patacom;
        let _conList = Object.keys(_conf).sort((a, b) => Number(a) - Number(b));
        let _myData = await PataFun.getInfo(call.uid);
        for (let index = 0; index < _conList.length; index++) {
            const element = Number(_conList[index]);
            // 未通关 已经经过排序，可以直接 break
            if (_myData.lv <= element) break
            /**已经领取 */
            if (_myData.gotarr.indexOf(element) != -1) continue
            _res.show = true
            _res.val.reward.show = true
        }
        // 扫荡判断
        let max = G.gc.com.pata_saodang.value + (PlayerShared.getMingDaoBuff(call.conn.gud, "zccg_sd") || 0);
        let prize = G.gc.pata[_myData.lv - 1]?.sdprize;
        _res.val.saodang.show = max - (_myData.saodangNum || 0) > 0 && !!prize
        _res.show = _res.show || _res.val.saodang.show
        return _res;
    }

    /**名望免费礼包及特权领取 红点 */
    static async renownHongDian(call: ApiCall) {
        let _res = {
            show: false
        };
        let _conf = G.gc.mw_com.gift
        let _myData = await G.mongodb.collection('playerInfo', 'juewei').findOne({uid: call.conn.uid, type: 'juewei'});
        // 无数据，有免费礼包
        if (!_myData) {
            _res.show = true
            return _res
        }

        for (let index = 0; index < _conf.length; index++) {
            const element = _conf[index];
            if (index == 0 && PublicShared.getToDayZeroTime(_myData.tequan.recTime || 0) == PublicShared.getToDayZeroTime(G.time)) {
                // 特权红点
                let buyLog = await PayFun.getPayLog(call.uid, element.payId);
                if (buyLog.length > 0) {
                    _res.show = true
                    return _res
                }
            }

            // 不是免费
            if (element.payId) continue

            /**已经领取最大次数 */
            if ((_myData.record?.[index] || 0) >= element.buyNum) continue
            _res.show = true
            break
        }
        return _res;
    }

    /**开服竞赛 */
    static async kaifujingsai(call: ApiCall): Promise<hongdianVal> {
        let status = kfjsFun.getStatus()
        // 超过活动显示时间后，不查询直接返回false
        if (status.type < 1 && PublicShared.getOpenServerDay() > R.values(G.gc.kfcb_content).slice(-1)[0].showDay[1] + 1) return {show: false}
        let data = await G.mongodb.cEvent('kaifujingsai').findOne({uid: call.uid, type: 'kaifujingsai'})
        let canGet = {}
        for (let i = 1; i <= 7; i++) {
            let prize = kfjsFun.getStatus(i)
            if (PublicShared.getOpenServerDay() <= prize.conf.showDay[1]) continue
            let rankKfjs = RankKfjs(i)
            let myRank = await rankKfjs.getRankSortByOne(call.uid)
            if (prize.type > 0 && !data?.record?.[i] && myRank >= 0) {
                canGet[i] = true
            }
        }

        if (R.values(canGet).length == 0) return {show: false}
        return {show: true, val: canGet}
    }

    /**周末礼包 */
    static async zhoumolibao(call: ApiCall): Promise<hongdianVal> {
        let _hd = (await HuoDongFun.gethdList(call, 9))[0]
        let gift = _hd?.data?.gift?.find(i => i.free)
        if (!gift) return {show: false}

        let data = await G.mongodb.cEvent('zhoumolibao').findOne({uid: call.uid, type: 'zhoumolibao'})
        let rec = data?.record?.[gift.id]
        if (rec && rec >= gift?.buyNum) return {show: false}
        return {show: true}
    }

}


export class HuoDongHongDianFun {
    /**所有可支持后台活动 红点 */
    static async houtaihdHongDian(call: ApiCall) {
        let _res = {
            show: false,
            val: {
                hdid: [],
                htype: [],
                hdxq: {}
            }
        };
        let _hdList = await HuoDongFun.gethdList(call)
        // let _hdList = await HuoDongFun.gethdList(call)
        for (let index = 0; index < _hdList.length; index++) {
            const element = _hdList[index];
            let ishd: hongdianVal = {show: false}
            if (element.htype == 1) {
                // 检测 htype 1 养成目标活动红点
                ishd = await this.yangchengmubiaoHongDian(call, element)
            }

            if (element.htype == 2) {
                // 检测 htype 2 掉落兑换活动红点
                ishd = await this.diaoluoduihuanHongDian(call, element)
            }

            if (element.htype == 3) {
                // 检测 htype 3 传说之路活动红点
                ishd = await this.chuanshuozhiluHongDian(call, element)
            }

            if (element.htype == 4) {
                // 检测 htype 4 自选礼包活动红点
                ishd = await this.zixuanlibaoHongDian(call, element)
            }

            if (element.htype == 5) {
                // 检测 htype 5 累计充值活动红点
                ishd = await this.leijichongzhiHongDian(call, element)
            }

            if (element.htype == 6) {
                // 检测 htype 6 七日登录活动红点
                ishd = await this.qiridengluHongDian(call, element)
            }
            if (element.htype == 8) {
                // 检测 htype 8 圣诞活动红点
                ishd = await this.christmasHongDian(call, element)
            }
            if (element.htype == 10) {
                // 检测 htype 10 破冰活动红点
                ishd = await this.pobinglibao(call, element)
            }
            if (element.htype == 14) {
                // 检测 htype 10 元旦活动红点
                ishd = await this.yuandan(call, element)
            }

            // 此活动有红点
            if (ishd.show) {
                _res.show = true
                _res.val.hdid.push(element.hdid)
                if (_res.val.htype.indexOf(element.htype) == -1) _res.val.htype.push(element.htype)
                _res.val.hdxq[element.hdid] = ishd
            }
        }
        return _res;
    }

    /**破冰礼包红点 */
    static async pobinglibao(call: ApiCall, _hd: ReqAddHuoDong): Promise<hongdianVal> {
        let gift = _hd?.data?.gift?.find(i => i.free == true && !i.payId)
        if (gift) return {show: true}

        let payIds = _hd?.data?.gift?.filter(i=>i.payId).map(i=>i.payId)
        let payLogs = await PayFun.getPayLogs(call.uid, payIds)

        // 取奖励列表，判断是否有可领取奖励
        let data = await G.mongodb.cEvent('pobinglibao').findOne({uid: call.uid, type: 'pobinglibao'})

        for (let item of _hd?.data?.gift){
            let rec = data?.record?.[item.id]?.length
            if (item.free== true && !item.payId) return {show: true}
            if (payLogs[item.payId]?.length && (!rec || rec < PublicShared.getDiff(payLogs[item.payId][0].time))) return {show: true}
        }

        return {show:false}
    }

    /**元旦活动红点 */
    static async yuandan(call: ApiCall, _hd: ReqAddHuoDong): Promise<hongdianVal> {

        let gift = _hd?.data?.gift?.find(i => i.free && !i.payId)

        // 取奖励列表，判断是否有可领取奖励
        let data = await G.mongodb.cEvent(`yuandan${_hd.hdid}`).findOne({uid: call.uid, type: `yuandan${_hd.hdid}`})

        if (gift && !data?.gift?.[gift.id]) return {show: true}

        if (data?.gameNum < _hd.data.gamefree) return {show: true}

        if (!PublicShared.chkSameDate(data?.qiandaoTime || 1, G.time)) {
            return {show: true}
        }

        for (const i in data.taskval) {
            if (data?.taskval[i] >= _hd?.data?.task?.[i]?.pval && !data?.taskfinish.find(v => v == i)) {
                return {show: true}
            }
        }
        return {show: false}
    }

    /**开服狂欢红点 */
    static async kfkhHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };
        let [isOpen, tips] = PublicShared.getOpenCond(call, "kaifukuanghuan")
        if (!isOpen) return _res;

        let db = await G.mongodb.cEvent('kaifukuanghuan').findOne({uid: call.uid, type: 'kaifukuanghuan'});
        let data = db || {
            receiveLogin: [],
            receiveBox: [],
            receiveTask: Object.fromEntries(Object.keys(G.gc.kaifukuanghuan.task).map(day => [day, []]))
        };
        // 登录奖励
        let day = PublicShared.getOpenServerDay(call.conn.gud.cTime);
        if (data.receiveLogin.length < day) _res.show = true;

        // 宝箱奖励
        if (!_res.show) {
            let _con = G.gc.kaifukuanghuan.taskBoxPrize;
            let finished = Object.values(data.receiveTask).map(fs => fs.length).reduce((a, b) => a + b);
            for (let index = 0; index < _con.length; index++) {
                const element = _con[index];
                if (data.receiveBox.includes(index)) continue;
                if (finished < element.total) continue;
                _res.show = true;
            }
        }

        // 任务奖励
        if (!_res.show) {
            let _taskcon = G.gc.kaifukuanghuan.task;
            let tasks = Object.values(G.gc.kaifukuanghuan.task as k_v<_gcType['kaifukuanghuan']['task']['1']>).map(tasks => tasks.map(task => task.taskType)).reduce((a, b) => a.concat(b));
            let taskFinished = await getTaskVal(call.conn.gud, [...new Set(tasks)]);
            let _keys = Object.keys(_taskcon);
            for (let index = 0; index < _keys.length; index++) {
                const element = _taskcon[_keys[index]];

                for (let indexTask = 0; indexTask < element.length; indexTask++) {
                    const _tmp = element[indexTask];
                    if (parseInt(_keys[index]) > day) break;    // 未开放
                    if (data.receiveTask[_keys[index]].includes(indexTask)) continue;
                    // 重复领取 和 条件未满足
                    if (_tmp.taskType != 'jjc_rank') {
                        if ((taskFinished[_tmp.taskType] || 0) < _tmp.total) continue;
                    } else {
                        if ((taskFinished[_tmp.taskType] || 0) > _tmp.total) continue;
                    }

                    _res.show = true;
                    break;
                }

                if (_res.show) break;
            }
        }
        return _res;
    }

    /**基金红点 */
    static async jijinHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false,
            val: {
                keys: []
            }
        };
        let jijintype: jijinType[] = ["dengjijijin", "guanqiajijin", "dayjijin", "tianshujijin"];
        let logs = await PayFun.getPayLogs(call.uid);
        for (let index = 0; index < jijintype.length; index++) {
            const element = jijintype[index];
            let conf = G.gc.jijin[element];

            // 相关数据
            let data = await G.mongodb.cEvent(element).findOne({uid: call.uid, type: element});
            let rec = data?.rec || {};        // 领取数据
            let val = await getVal(call, logs, element);
            let payId = element == 'tianshujijin' ? 'zhongshenka' : element;
            let isPay = logs?.[payId]?.length > 0;
            for (let taskindex = 0; taskindex < conf.length; taskindex++) {
                const elementtask = conf[taskindex];

                if (val < elementtask.total) continue;   // 未完成
                let hasPt = elementtask.pt.length > 0;
                let hasTq = elementtask.tq.length > 0;
                let getPt = !hasPt || rec[taskindex]?.pt == true;
                let getTq = !hasTq || rec[taskindex]?.tq == true;

                if (getPt && !getTq && !isPay) continue;           // 购买礼包后才可以领取奖励
                if (getPt && getTq) continue;   // 奖励已领取

                _res.show = true;
                _res.val.keys.push(element);
                break;
            }
            // if (_res.show) break;
        }
        return _res;
    }

    /**追杀令红点 */
    static async zhuishalingHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false,
            val: {
                "task": [],
                "zhanling": 0
            }
        };

        let [isOpen, tips] = PublicShared.getOpenCond(call, "zhanling")
        if (!isOpen) return _res;

        // 任务奖励
        let conf = G.gc.zhanling.task;
        let _mydata = await G.mongodb.cEvent('zhanling').findOne({uid: call.uid, type: 'zhanling'});
        let tasks = G.gc.zhanling.task.map(t => {
            return {type: t.type as 'day' | 'week' | 'round', key: t.taskId};
        });
        let taskFinished = await ZhanLingTasks.getLog(call.uid, tasks);
        for (let index = 0; index < conf.length; index++) {
            const element = conf[index];
            if (element.taskId == 'tqexp' && !_mydata?.isPay) continue;
            if ((_mydata?.taskRec || []).includes(index)) continue;
            // let taskVal = await ActionLog.getDayLog(call.uid, element.taskId);
            let _key = `${element.type}@${element.taskId}`;
            let taskVal = taskFinished[_key];
            if (taskVal < element.total) continue;
            _res.show = true;
            if (!_res.val["task"].includes(element.type)) {
                _res.val["task"].push(element.type);
            }
            // break;   前端要求加 key
        }

        // 战令奖励
        let rec = _mydata?.rec || {};
        let val = _mydata?.lv || 0;
        let isPay = _mydata?.isPay;
        let _conf = G.gc.zhanling.prize;
        for (let zlindex = 0; zlindex < _conf.length; zlindex++) {
            const zlelement = _conf[zlindex];
            if (val < zlelement.lv) continue;   // 未完成
            let hasPt = zlelement.pt.length > 0;
            let hasTq = zlelement.tq.length > 0;
            let getPt = !hasPt || rec[zlindex]?.pt == true;
            let getTq = !hasTq || rec[zlindex]?.tq == true;

            if (getPt && !getTq && !isPay) continue;           // 购买礼包后才可以领取奖励
            if (getPt && getTq) continue;   // 奖励已领取

            _res.show = true;
            _res.val["zhanling"] = 1;
            break;
        }
        return _res;
    }

    /**七日登录红点 */
    static async qiridengluHongDian(call: ApiCall, hdCon: ReqAddHuoDong) {
        let _res: hongdianVal = {
            show: false
        };
        let _con = hdCon.data.arr;
        let day = await ActionLog.getRetainLog(call.uid, `login_day_qiridenglu_${hdCon.hdid}`);
        let _dbType: `qiridenglu${number}` = `qiridenglu${hdCon.hdid}`
        let _mydata = await G.mongodb.cEvent(_dbType).findOne({uid: call.uid, type: _dbType});
        for (let index = 0; index < _con.length; index++) {
            const element = _con[index];
            if (element.day > day) continue;
            if (_mydata?.recPrize?.includes(index)) continue;
            _res.show = true;
            break;
        }
        return _res;
    }

    // 一百抽 子函数
    static async yibaochouhd(conf, finish: number, recArr: number[]) {
        let ishd: 0 | 1 = 0;
        for (let index = 0; index < conf.length; index++) {
            const element = conf[index];
            if (finish < element.total) continue;
            if (recArr.includes(index)) continue;
            ishd = 1;
            break;
        }
        return ishd;
    }

    /**一百抽红点 */
    static async yibaichouHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };
        let [isOpen, tips] = PublicShared.getOpenCond(call, "yibaichou")
        if (!isOpen) return _res;

        let _con = G.gc.yibaichou;
        let _type = ['online', 'login'];
        let _mydata = await G.mongodb.cEvent('yibaichou').findOne({uid: call.uid, type: 'yibaichou'});
        for (let index = 0; index < _type.length; index++) {
            const element = _type[index];

            let conf = G.gc.yibaichou[element + 'Prize'];
            let finish = element == 'login' ? call.conn.gud.loginDays : call.conn.gud.onlineTime;
            let recArr: number[] = _mydata?.[element + 'Rec'] || [];
            let ishd = await this.yibaochouhd(conf, finish, recArr);
            if (ishd == 1) {
                _res.show = true;
                break;
            }
        }
        return _res;
    }

    /**伙伴招募红点 */
    static async huobanzhaomuHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };

        let [isOpen, tips] = PublicShared.getOpenCond(call, "huobanzhaomu")
        if (!isOpen) return _res;

        let _con = G.gc.huobanzhaomu;
        let _mydata = await G.mongodb.cEvent('huobanzhaomu').findOne({uid: call.uid, type: 'huobanzhaomu'});
        for (let index = 0; index < _con.length; index++) {
            const element = _con[index];
            if (_mydata?.rec.includes(index)) continue;  // 已领取
            if (element.gudKey && call.conn.gud[element.gudKey] < element.total) continue;     // 未达成
            if (!element.gudKey && (_mydata?.rec?.length || 0) < _con.length - 1) continue;    // 大奖资格不够
            _res.show = true;
            break;
        }
        return _res;
    }

    /**累计充值红点 */
    static async leijichongzhiHongDian(call: ApiCall, hdCon: ReqAddHuoDong) {
        let _res: hongdianVal = {
            show: false
        };
        let _dbType: `leijichongzhi${number}` = `leijichongzhi${hdCon.hdid}`
        let _con = hdCon.data.tasks;
        let db = await G.mongodb.cEvent(_dbType).findOne({uid: call.uid, type: _dbType});
        let _mydata = db || {sTime: PublicShared.getToDayZeroTime(G.time), recIndex: []};
        let payNum = await PayFun.getPayDaysAllPayNum(call.uid, hdCon.stime, hdCon.etime);
        for (let index = 0; index < _con.length; index++) {
            const element = _con[index];
            if (_mydata.recIndex.includes(index)) continue;
            if (payNum < element.total) continue;
            _res.show = true;
            break;
        }
        return _res;
    }

    /**七日累充红点 */
    static async qirileichongHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };
        let db = await G.mongodb.cEvent('qirichongzhi').findOne({uid: call.uid, type: 'qirichongzhi'});
        let _mydata = db || {round: 0, sTime: PublicShared.getToDayZeroTime(G.time), recIndexs: []};
        let _con = G.gc.qirichongzhi[_mydata.round];
        let finished = await PayFun.getPayDaysAllPayNum(call.uid, _mydata.sTime, _mydata.sTime + G.gc.qirichongzhi[_mydata.round].time);
        for (let index = 0; index < _con.tasks.length; index++) {
            const element = _con.tasks[index];
            if (_mydata.recIndexs.includes(index)) continue;
            if (finished < element.total) continue;
            _res.show = true;
            break;
        }
        return _res;
    }

    /**节日 子函数 */
    static async jieriHD(call: ApiCall, _conf, recIndex, _type, _finish: number) {
        let ishd: 0 | 1 = 0;
        for (let index = 0; index < _conf.length; index++) {
            const element = _conf[index];
            if (_type == 'task') _finish = await ActionLog.getDayLog(call.uid, element.taskId);
            if (_finish < element.total) continue;
            if (recIndex.includes(index)) continue;
            ishd = 1;
            break;
        }
        return ishd;
    }

    /**节日红点 */
    static async jieriHongDian(call: ApiCall) {
        let _res: hongdianVal = {
            show: false
        };
        let db = await G.mongodb.cEvent('jierihuodong').findOne({uid: call.uid, type: 'jierihuodong'});
        let _mydata = db || {refreshTime: G.time, recTask: [], recLogin: []};
        let _types = ['login', 'task'];
        let finish = call.conn.gud.loginDays;
        for (let index = 0; index < _types.length; index++) {
            const element = _types[index];
            let _conf = element == 'login' ? G.gc.jierihuodong.denglufuli : G.gc.jierihuodong.huodongrenwu;
            let recIndex = element == 'login' ? (_mydata?.recLogin || []) : (_mydata?.recTask || []);
            let ishd = await this.jieriHD(call, _conf, recIndex, element, finish);
            if (ishd == 1) {
                _res.show = true;
                break;
            }
        }
        return _res;
    }

    /**圣诞节活动红点 */
    static async christmasHongDian(call: ApiCall, hdCon: ReqAddHuoDong) {
        let _res: hongdianVal = {
            show: false,
        };

        let _hdCon = hdCon.data;
        let stime = hdCon.stime
        let _mydata = await Christmasfun.getMyData(call, hdCon.hdid);
        let _tasks = hdCon.data.task;   // 所有任务 taskid 为key

        for (let indextask = 0; indextask < Object.keys(_tasks).length; indextask++) {
            const elementtask = Object.keys(_tasks)[indextask];
            let _tmp = _tasks[elementtask];
            if (_tmp.pval <= (_mydata.taskval[elementtask] || 0) && !_mydata.taskfinish.includes(elementtask)) {
                // 任务完成且没有领取
                _res.show = true;
                return _res;
            }
        }

        let libaos = _hdCon.libao
        for (let indexlibao = 0; indexlibao < Object.keys(libaos).length; indexlibao++) {
            const elementlibao = Object.keys(libaos)[indexlibao];
            let _tmp = _tasks[elementlibao];
            if (_tmp.payid) continue
            let _buyNum = _mydata.libao[elementlibao] || 0
            if (_buyNum < _tmp.buynum) {
                _res.show = true;
                return _res;
            }
        }
        let _diff = PublicShared.getDiff(stime)
        // 循环判断是否有可以领取的
        for (let i = 0; i < _diff; i++) {
            if (_mydata.qiandao.includes(i)) continue
            _res.show = true;
            return _res;
        }
        let need = _hdCon.gameneed;
        // 判断消耗是否满足
        let meet = await PlayerFun.checkNeedIsMeet(call, need, false);
        if (meet.isOk == true) {
            _res.show = true;
            return _res;
        }
        let zhanling = _hdCon.zhanling
        for (let indexzhanling = 0; indexzhanling < zhanling.length; indexzhanling++) {
            if (!_mydata.pt.includes(indexzhanling)) {
                _res.show = true;
                return _res;
            }
            if (_mydata.pay && !_mydata.gj.includes(indexzhanling)) {
                _res.show = true;
                return _res;
            }
        }

        return _res;
    }


    /**养成目标红点 */
    static async yangchengmubiaoHongDian(call: ApiCall, hdCon: ReqAddHuoDong) {
        let _res: hongdianVal = {
            show: false,
        };

        let _hdCon = hdCon.data;
        let _mydata = await YangChengMuBiaofun.getMyData(call, hdCon.hdid);

        let _tasks = {};   // 所有任务 taskid 为key
        Object.values(_hdCon.tasklist).map(l => {
            return Object.assign(_tasks, l);
        });

        let _ishd = 0;
        for (let indextask = 0; indextask < Object.keys(_tasks).length; indextask++) {
            const elementtask = Object.keys(_tasks)[indextask];
            let _tmp = _tasks[elementtask];
            if (_tmp.pval <= (_mydata.taskval[elementtask] || 0) && !_mydata.finishid[_tmp.type].includes(parseInt(elementtask))) {
                // 任务完成且没有领取
                _res.show = true;
                _ishd = 1;
                break;
            }
        }

        if (_ishd != 1) {
            let _gift = _hdCon.gift.filter(l => (!l.payId && l.need.length <= 0) || l.free);
            for (let indexgift = 0; indexgift < _gift.length; indexgift++) {
                const elementgift = _gift[indexgift];
                let buyNum = _mydata.record?.[indexgift] || 0;
                if (buyNum < elementgift.buyNum) {
                    _res.show = true;
                    break;
                }
            }
        }
        return _res;
    }

    /**掉落兑换红点 */
    static async diaoluoduihuanHongDian(call: ApiCall, hdCon: ReqAddHuoDong): Promise<hongdianVal> {
        let _dbType: `diaoluoduihuan${number}` = `diaoluoduihuan${hdCon.hdid}`
        // 取出用户已领取的数据
        let data = await G.mongodb.cEvent(_dbType).findOne({uid: call.uid, type: _dbType})
        // 循环活动商店，判断免费与领取
        let confEvent = Object.keys(hdCon.data.event).filter(k => Array.isArray(hdCon.data.event[k]))
        for (let key of confEvent) {
            let item = hdCon.data.event[key]
            for (let i in item) {
                if (item[i].free && !(data && data.record && data.record[key] && data.record[key][i])) return {show: true}
            }
        }
        return {show: false};
    }

    /**传说之路 */
    static async chuanshuozhiluHongDian(call: ApiCall, hdCon: ReqAddHuoDong): Promise<hongdianVal> {
        let _dbType: `chuanshuozhilu${number}` = `chuanshuozhilu${hdCon.hdid}`

        let task = hdCon.data
        let db = await G.mongodb.cEvent(_dbType).findOne({uid: call.uid, type: _dbType});
        let info: Partial<typeof db.info['']> = db?.info?.[task.hid] || {};

        for (let conf of task.task) {
            if (info[conf.type] >= conf.total && !(info.rec || []).includes(conf.idx)) return {show: true};
        }

        if (info.rec?.length >= task.box.total && !info.box) return {show: true};

        return {show: false};
    }

    /**自选礼包红点 */
    static async zixuanlibaoHongDian(call: ApiCall, hdCon: ReqAddHuoDong): Promise<hongdianVal> {
        let _dbType: `zixuanlibao${number}` = `zixuanlibao${hdCon.hdid}`
        let db = await G.mongodb.cEvent(_dbType).findOne({uid: call.uid, type: _dbType});
        if (!db?.rec) {
            return {show: true}
        }

        return {show: false};
    }

    /**月度基金 */
    static async yuedujijinHongDian(call: ApiCall): Promise<hongdianVal> {
        let pays = 0;
        let payIds = G.gc.yuedujijin.map(v => v.payId);
        let obj: k_v<payLog[]> = {};

        for (let id of payIds) {
            let logs = obj[id] = await PayFun.getPayLog(call.uid, id);
            if (logs.length > 0) pays++;
        }

        if (pays < 1) return {show: false};

        for (let conf of G.gc.yuedujijin) {
            let id = conf.payId;
            let logs = obj[conf.payId];
            if (logs.length < 1) continue;
            let db = await G.mongodb.cEvent(id as `${number}jijin`).findOne({
                uid: call.uid,
                type: id as `${number}jijin`
            });
            let rec = db?.rec || [];
            let days = db?.days || 0;
            let round = db?.round || 0;
            if (rec.length < days + 1 && rec.length < conf.prize.length * (round + 1)) return {show: true};
        }

        return {show: false};
    }

    /** 黑市活动 */
    static async heiShihd(call: ApiCall): Promise<hongdianVal> {
        let _res: hongdianVal = {
            show: false,
            val: {
                meirijingxuan: {},
                jitianhaoli: {},
                niudanji: {}
            }
        };
        _res.val.meirijingxuan = await this.heiShiHongDian(call)
        // _res.val.jitianhaoli = await this.heiShiLCHongDian(call)
        _res.val.niudanji = await this.heiShiNiuDanJi(call)
        Object.values(_res.val).forEach(x => _res.show = _res.show || x.show)
        return _res
    }

    /**黑市 每日精选 */
    static async heiShiHongDian(call: ApiCall): Promise<hongdianVal> {
        let payKey = "136Gift1"
        let _res: hongdianVal = {
            show: false,
            val: {stask: []}
        };
        let db = await G.mongodb.cEvent('136Gift').findOne({uid: call.uid, type: '136Gift'});
        let payData = await PayFun.getPayLogs(call.uid)
        let payLen = (payData[payKey] || []).length
        let isBuy = !(!payLen || payData[payKey][payLen - 1].eTime < G.time)
        let _myData = (db && db.refreshTime >= PublicShared.getToDayZeroTime() && db.recIndex) ? db.recIndex : [];
        let _con = G.gc["dixiaheishi"]['136Gift'];
        for (let index = 1; index < _con.length; index++) {
            const element = _con[index];
            // if (element.payId && !isBuy) {
            if (element.payId && !isBuy) {
                continue;
            }
            if (_myData.includes(index)) {
                continue;
            }
            _res.val.stask.push(index)
            if (index > 1 && !_res.val.stask.includes(0)) _res.val.stask.push(0)
            _res.show = true
        }
        return _res;
    }

    /**黑市 积天豪礼 */
    // static async heiShiLCHongDian(call: ApiCall): Promise<hongdianVal> {
    //     let _res: hongdianVal = {
    //         show: false
    //     };
    //     let db = await G.mongodb.cEvent('15leichong').findOne({uid: call.uid, type: '15leichong'});
    //
    //     if (!db) return _res;
    //
    //     let _con = G.gc.shiwuleichong.data[db.index];
    //     let payDay = await PayFun.getPayDaysBuyPayNum(call.uid, db.sTime, db.sTime + _con.time, G.gc.shiwuleichong.dayPayNeed);
    //     for (let index = 0; index < _con.tasks.length; index++) {
    //         const element = _con.tasks[index];
    //         if (db.recIndex.includes(index)) continue;
    //         if (payDay < element.total) continue;
    //         _res.show = true;
    //         break;
    //     }
    //     return _res;
    // }

    /**黑市 扭蛋机 */
    static async heiShiNiuDanJi(call: ApiCall): Promise<hongdianVal> {
        // 查询配置，获取等级限制
        let openCondConf = G.gc.openCond['hs_btn_ndj']
        let _res: hongdianVal = {
            show: false
        };
        // 等级不满足，上锁，不查询红点。
        if (call.conn.gud.lv < openCondConf.display.lv) return _res
        let db = await G.mongodb.cEvent('niudanji').findOne({uid: call.uid, type: 'niudanji'});
        let useNum = db?.useNum || 0
        let hasNum = Math.floor(call.conn.gud.payExp / G.gc.niudanji.pay2num)
        _res.show = useNum < hasNum
        return _res
    }
}


export class HongDianChange {
    /**红点 change */
    static async sendChangeKey(uid: string, key: hongdianKey[]) {
        G.server.sendMsgByUid(uid, 'msg_s2c/HongDianChange', key);
    }
}

