import {ApiCall} from "tsrpc";
import {CollectionWanted} from '../../module/collection_wanted';
import {ChatFun} from '../../public/chat';
import {FightFun} from '../../public/fight';
import {formatNpcData} from '../../shared/fightControl/fightFun';
import {joinFightData} from '../../shared/fightControl/fightType';
import {ReqOpen, ResOpen} from "../../shared/protocols/gonglukuangbiao/PtlOpen";
import {player} from '../../shared/protocols/user/type';
import {PublicShared} from '../../shared/public/public';

export default async function (call: ApiCall<ReqOpen, ResOpen>) {

    let db: Partial<CollectionWanted> = await G.mongodb.collection('wanted').findOne({uid: call.uid}) || {};

    if (!db.refreshTime || db.refreshTime < PublicShared.getToDayZeroTime()) {
        let cut = G.gc.gonglukuangbiao.timeDeduct;
        let w = (db?.wanted || 0) - cut < 0 ? 0 : db.wanted - cut;

        db.wanted = w;
        db.toDayWin = {
            '0': 0,
            '1': 0,
            '2': 0
        };
        db.toDayBuyNum = 0;
        db.toDayUseNum = 0;
        db.toDayBeiFightNum = 0;
        db.refreshTime = G.time;

        G.mongodb.collection('wanted').updateOne({uid: call.uid}, {
            $set: {
                wanted: db.wanted,
                toDayWin: db.toDayWin,
                toDayBuyNum: db.toDayBuyNum,
                toDayUseNum: db.toDayUseNum,
                toDayBeiFightNum: db.toDayBeiFightNum,
                refreshTime: G.time,
            }
        }, {upsert: true});
    }
    if (!db.enemys) {
        db.enemys = await refreshEnemys(call);
        G.mongodb.collection('wanted').updateOne({uid: call.uid}, {
            $set: {
                enemys: db.enemys
            }
        }, {upsert: true});
    }

    call.succ(db as any);
}

let lastRefreshTime: number
let enemyObject: object = {}

/**
 * 每小时刷新公路狂飙用户，功能超过30级开放，只查询30级以上的用户，超过80级的，80级到100级为一档
 */
async function checkAndRefreshEnemy() {
    if (lastRefreshTime + 3600 > G.time) return
    lastRefreshTime = G.time
    for (let i = 3; i <= 8; i++) {
        let users = await G.mongodb.collection('user').aggregate([
            {
                $match: {
                    $and: [
                        {lv: {$gte: i * 10}},
                        {lv: {$lt: i == 8 ? 101 : (i + 1) * 10}},
                    ]
                }
            },
            {
                $project: {uid: 1}
            },
            {
                $sample: {size: 100}
            }
        ]).toArray()
        let dbUser = await G.mongodb.find('wanted', {uid: {$in: users.map(u => u.uid)}}, ['uid', 'wanted']);

        enemyObject[i] = dbUser || []
    }
}

export async function refreshEnemys(call: ApiCall) {
    if (!lastRefreshTime) await checkAndRefreshEnemy()

    let lvDw = Math.floor(call.conn.gud.lv / 10 > 8 ? 8 : call.conn.gud.lv / 10)

    let dbUser = enemyObject[lvDw] || []

    let enemys: joinFightData[] = [];

    // 自带reverse有时会失效
    let configs = R.reverse(G.gc.gonglukuangbiao.config)
    for (let idx = 0; idx < configs.length; idx++) {
        let conf = configs[idx]
        let needMax = configs[idx + 1]?.need || G.gc.gonglukuangbiao.wanted[idx].wanted[1]
        let filter = dbUser.filter(u => conf.need <= u.wanted && u.wanted < needMax);
        let uids = filter.map(f => f.uid);
        dbUser.remove(u => uids.includes(u.uid));
        let enemy = uids.length > 0 ? await FightFun.getPlayerFightData(uids.random()) : formatNpcData(configs[0].npc.random());
        if (!enemy) enemy = formatNpcData(configs[0].npc.random())
        if (enemy.player.isNpc) enemy.player.name = G.gc.gonglukuangbiao.npcname.random()
        enemy["wanted"] = !enemy.player.isNpc ?
            filter.filter(u => u.uid = enemy.player.uid)[0].wanted :
            PublicShared.randomNum(G.gc.gonglukuangbiao.wanted[0].wanted[0], G.gc.gonglukuangbiao.wanted[0].wanted[1])
        enemys.push(enemy);
    }
    checkAndRefreshEnemy()
    return enemys.reverse();
}

export async function checkNewDay(gud: player, last: number, cur: number) {

    G.mongodb.collection('wanted').findOne({uid: gud.uid}).then(db => {
        if (!db) return;
        let cut = G.gc.gonglukuangbiao.timeDeduct;
        let w = db.wanted - cut < 0 ? 0 : db.wanted - cut;
        G.mongodb.collection('wanted').updateOne({uid: gud.uid}, {$set: {wanted: w}});

        if (w >= G.gc.gonglukuangbiao.config[0].need) {

            ChatFun.newMsg({
                type: 'local',
                msg: G.gc.pmd.glkb_pmd,
                time: G.time,
                sender: 'system',
                otherData: {
                    pmd: true,
                    args: [gud.name]
                }
            });
        }
    });
}