import {OptionalId, UpdateFilter} from 'mongodb';
import {ApiCall} from 'tsrpc';
import {playerInfoType} from '../module/collection_palyerInfo';
import {CollectionXstask} from '../module/collection_xstask';
import {PublicShared} from '../shared/public/public';
import {ActionLog} from "./actionLog/actionLog";


export class XstaskFun {
    /**所有玩家的悬赏任务缓存 */
    static uidTask: k_v<CollectionXstask[]> = {};

    /**获取单个悬赏任务 */
    static async getTask(uid: string, _id: string) {
        return this.uidTask[uid]?.find(task => task._id == _id) || await G.mongodb.collection('xstask').findOne({
            uid: uid,
            _id: G.mongodb.conversionId(_id)
        });
    }

    /**获取所有悬赏任务 */
    static async getAllTask(uid: string) {
        let taskList = this.uidTask[uid];

        if (!taskList) {
            taskList = this.uidTask[uid] = (await G.mongodb.collection('xstask').find({uid: uid}).toArray()).map(task => G.mongodb.conversionIdObj(task));
        }
        ;

        return taskList;
    }

    /**完成任务标记 */
    static async finishTask(uid: string, _id: string) {
        // 修改数据库
        G.mongodb.collection('xstask').updateOne({
            uid: uid,
            _id: G.mongodb.conversionId(_id)
        }, {$set: {'receiveData.rec': true}});
        // 修改缓存
        let index = this.uidTask[uid]?.findIndex(task => task._id == _id);
        this.uidTask[uid][index].receiveData.rec = true
        return
    }

    /**更新任务单个 */
    static async updateTask(uid: string, _id: string, taskId: string) {
        G.mongodb.collection('xstask').updateOne({
            uid: uid,
            _id: G.mongodb.conversionId(_id)
        }, {$unset: {receiveData: 1}, $set: {taskId: taskId}});
        let index = this.uidTask[uid]?.findIndex(task => task._id == _id);
        delete this.uidTask[uid][index].receiveData;
        this.uidTask[uid][index].taskId = taskId;
    }

    /**删除单个悬赏任务 */
    static async delTask(uid: string, _id: string) {

        let task = this.uidTask[uid]?.find(task => task._id == _id);
        task && this.uidTask[uid].removeOne(task);

        G.mongodb.collection('xstask').deleteOne({uid: uid, _id: G.mongodb.conversionId(_id)});
    }

    /**删除多个悬赏任务 */
    static async delTasks(uid: string, _id: string[]) {

        for (let id of _id) await this.delTask(uid, id);
    }

    /**添加多个悬赏任务 */
    static async addTasks(uid: string, taskArr: { taskId: string; }[]) {

        let taskList = taskArr.map(task => {
            return {
                taskId: task.taskId,
                uid: uid,
            };
        });
        let result = await G.mongodb.collection('xstask').insertMany(taskList);

        this.uidTask[uid] = this.uidTask[uid] || [];
        taskList.forEach((task, index) => {
            this.uidTask[uid].push(G.mongodb.conversionIdObj({
                _id: result.insertedIds[index],
                ...task
            }));
        });

        return this.uidTask[uid];
    }

    /**派遣任务任务 */
    static async receiveTask(uid: string, _id: string, d: CollectionXstask['receiveData']) {
        let cache = this.uidTask[uid]?.find(task => task._id == _id);
        if (cache) cache.receiveData = d;
        G.mongodb.collection('xstask').updateOne({
            uid: uid,
            _id: G.mongodb.conversionId(_id)
        }, {$set: {receiveData: d}});
    }

    /**获取所有已被派遣的英雄 */
    static async getAllReceiveHero(uid: string) {
        let heroIds: string[] = [];
        let allTask = await this.getAllTask(uid);

        allTask.forEach(task => heroIds = heroIds.concat(task.receiveData?.heros || []));

        return heroIds;
    }

    /**获取悬赏任务记录信息 */
    static async getInfo(uid: string) {
        return await G.mongodb.collection('playerInfo', 'xstask').findOne({uid: uid, type: 'xstask'});
    }

    /**修改悬赏任务记录信息 */
    static async changeInfo(uid: string, change: Pick<UpdateFilter<OptionalId<playerInfoType['xstask']>>, '$inc' | '$set'>) {

        G.mongodb.collection('playerInfo', 'xstask').updateOne(
            {uid: uid, type: 'xstask'},
            change,
            {upsert: true}
        );
    }

    /**随机任务 */
    static randomTasks(lv: number, num: number) {
        let tasks = Object.values(G.gc.xstask).filter(task => G.gc.xstaskcom.lv[lv].taskColor.includes(task.colour)).sort(function () {
            return Math.random() - 0.5;
        });

        return (PublicShared.randomDropGroup(0, num, [tasks] as any) as any as typeof tasks).map(v => {
            return {
                taskId: v.id.toString()
            };
        });
    }

    /**红点 */
    static async getHongDian(call: ApiCall) {
        let _res = {
            show: false
        };
        let _xstasks = await this.getAllTask(call.uid);
        _res.show = _xstasks.every(v => !v.receiveData);
        for (let index = 0; index < _xstasks.length; index++) {
            const element = _xstasks[index];
            // 未派遣
            if (!element.receiveData) continue;
            let taskConf = G.gc.xstask[element?.taskId];
            // 派遣时间不足
            if (element.receiveData.time + taskConf.time > G.time) continue;
            _res.show = true;
            break;
        }
        return _res;
    }

    /**
     * 刷新每天派遣次数，每天上限8次
     */
    static async receiveNum(uid: string, refresh = false) {
        if (refresh) {
            G.mongodb.cEvent('xstask').updateOne({uid: uid, type: 'xstask'},
                {$set: {refreshTime: G.time, receiveNum: 0}}, {upsert: true});
        } else {
            ActionLog.addDayLog(uid, { key: "xstask/Receive/Num", val: 1 });
            G.mongodb.cEvent('xstask').updateOne({uid: uid, type: 'xstask'},
                {$inc: {receiveNum: 1}}, {upsert: true});
        }

    }
}