import { Application, BackendSession, ChannelService, HandlerService, pinus } from "pinus";
import { GVG_ACTIVE_TYPE, GVG_ITEM, GVG_PERIOD, ITEM_CHANGE_REASON, REDIS_KEY, ROLE_SELECT, STATUS, TASK_TYPE, VESTIGE_OPP_STATUS, VESTIGE_STATUS, WAR_TYPE } from "../../../consts";
import { BattleRecordModel } from "../../../db/BattleRecord";
import { GVGLeagueModel } from "../../../db/GVGLeague";
import { GVGUserItemModel } from "../../../db/GVGUserItem";
import { GVGVestigeLeagueRankModel } from "../../../db/GVGVestigeLeagueRank";
import { GVGVestigeLockModel } from "../../../db/GVGVestigeLock";
import { GVGVestigeRankModel } from "../../../db/GVGVestigeRank";
import { GVGVestigeRecModel, GVGVestigeRecUpdate } from "../../../db/GVGVestigeRec";
import { GVGVestigeSumRankModel } from "../../../db/GVGVestigeSumRank";
import { HeroModel } from "../../../db/Hero";
import { RoleModel } from "../../../db/Role";
import { GVGVestigeOppLineup, VestigeRank } from "../../../domain/gvgField/returnData";
import { RoleRankInfo } from "../../../domain/rank";
import { getRemoteRplFilePath, getRemoteRplPrefix } from "../../../pubUtils/battleUtils";
import { gameData } from "../../../pubUtils/data";
import { GVG } from "../../../pubUtils/dicParam";
import { RewardInter } from "../../../pubUtils/interface";
import { resResult } from "../../../pubUtils/util";
import { isHeroHidden } from "../../../services/dataService";
import { calBreakGoods, checkHeroIsUsedInOtherVestige, checkVestige, checkVestigeOppStatus, checkVestigeRank, generateAttackHeroInfo, generateAttackInfo, generateDefenseInfo, getDayKeyInfo, getMyVestigeRank, getOppDetailData, getOppPlayerByRanks, getVestigeRecStatus, getVestigeRank, getVestigeUsedHeroes, isRobot, refreshVestigeOppRanks, saveScoreToRank, updateMyVestigeRank, saveVestigeRankSchedule, calVestigeLeagueBoxRewards, checkFightTime, savePlayerRank } from "../../../services/gvg/gvgFightService";
import { addGVGReward, combinePushItem, handleGVGCost } from "../../../services/gvg/gvgItemService";
import { addGVGActive } from "../../../services/gvg/gvgPrepareService";
import { addVestigeBattleEndRec } from "../../../services/gvg/gvgRecService";
import { getGroupKey, getGVGPeriodData } from "../../../services/gvg/gvgService";
import { checkBattleHeroesByHid } from "../../../services/normalBattleService";
import { Rank } from "../../../services/rankService";
import { getAllServerName } from "../../../services/redisService";
import { checkGVGTask } from "../../../services/task/taskService";

export default function (app: Application) {
    new HandlerService(app, {});
    return new GVGProduceHandler(app);
}

export class GVGProduceHandler {
    channelService: ChannelService;
    constructor(private app: Application) {
        this.channelService = app.get('channelService');
    }

    // 遗迹页面
    async getVestige(msg: { vestigeId: number }, session: BackendSession) {
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const guildCode = session.get('guildCode');
        const { vestigeId } = msg;

        let { configId, period } = getGVGPeriodData();
        if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);

        if(!await checkVestige(serverId, vestigeId)) {
            return resResult(STATUS.GVG_VESTIGE_ERR);
        }

        const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let groupKey = await getGroupKey(serverId);

        let dicRankMap = gameData.gvgVestige.get(vestigeId);
        if(!dicRankMap) return resResult(STATUS.DIC_DATA_NOT_FOUND);

        let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId, myLeague);
        if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let { rank, lineup, oppRanks, refreshCnt } = myVestigeRank;

        let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0);
        let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, oppRanks);
        let usedHeroes = await getVestigeUsedHeroes(roleId, vestigeId);

        return resResult(STATUS.SUCCESS, {
            vestigeId,
            myRank: rank,
            score: dicRankMap?.get(rank)?.score||0,
            lineup, lineupCe,
            oppPlayers,
            refreshCnt,
            usedHeroes
        })
    }

    // 编辑阵容
    async saveLineup(msg: { vestigeId: number, lineup: [{ actorId: number, dataId: number, order: number }] }, session: BackendSession) {

        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const { vestigeId, lineup: heroes } = msg;

        if(!await checkVestige(serverId, vestigeId)) {
            return resResult(STATUS.GVG_VESTIGE_ERR);
        }
        let { configId, period } = getGVGPeriodData();
        if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
        let groupKey = await getGroupKey(serverId);

        let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId);
        if(!myVestigeRank) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        for(let { actorId } of heroes) {
            if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN);
        }
        let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId));
        if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
        // 检查武将是否在其他遗迹中使用了
        if(await checkHeroIsUsedInOtherVestige(roleId, vestigeId, heroes)) return resResult(STATUS.GVG_VESTIGE_HERO_USED);

        let lineup = heroes.map(hero => {
            let curHero = dbHeroes.find(cur => cur.hid == hero.actorId);
            return { actorId: curHero.hid, dataId: hero.dataId, order: hero.order, ce: curHero.ce }
        });
        let vestigeRank = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { lineup, hasDefense: true });

        return resResult(STATUS.SUCCESS, {
            vestigeId,
            lineup: vestigeRank.lineup,
            lineupCe: vestigeRank.lineup.reduce((pre, cur) => pre + cur.ce, 0),
        });
    }

    // 获取对手阵容消息
    async getOppLineup(msg: { vestigeId: number, roleId: string, rank: number }, session: BackendSession) {
        const roleId: string = session.get('roleId');
        const serverId: number = session.get('serverId');
        const guildCode = session.get('guildCode');

        let { vestigeId, roleId: targetRoleId, rank } = msg;

        if(!await checkVestige(serverId, vestigeId)) {
            return resResult(STATUS.GVG_VESTIGE_ERR);
        }
        let myVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, roleId); // 我在这个遗迹的排名

        const serverNames = await getAllServerName();

        let isRobot = targetRoleId.startsWith('robot');
        let result = new GVGVestigeOppLineup(vestigeId);
        result.setMyRank(myVestigeRank?.rank||0);
        let dicGVGVestige = gameData.gvgVestige.get(vestigeId)?.get(rank);
        if(!dicGVGVestige) return resResult(STATUS.DIC_DATA_NOT_FOUND);

        const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        if(isRobot) {
            let dicWar = gameData.war.get(dicGVGVestige?.warId);
            let dicWarJson = gameData.warJson.get(dicWar.dispatchJsonId);
            result.setRobot(dicGVGVestige, dicWarJson, serverNames[serverId]);
        } else {
            let hisVestigeRank = await GVGVestigeRankModel.findByRole(vestigeId, targetRoleId);
            if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND);

            let role = await RoleModel.findByRoleId(hisVestigeRank.roleId, 'roleId roleName serverId guildName title lv heads head spines spine frames frame')
            if(!hisVestigeRank) return resResult(STATUS.GVG_VESTIGE_TARGET_NOT_FOUND);

            let hids = hisVestigeRank.lineup?.map(cur => cur.actorId)||[];
            let heroes = await HeroModel.findByHidRange(hids, targetRoleId, 'hid skinId quality star colorStar lv ce');
            const { leagueCode, name } = myLeague;
            result.setPlayer(dicGVGVestige, role, heroes, serverNames, name, leagueCode);
        }
        return resResult(STATUS.SUCCESS, result);
    }

    // 刷新对手
    async refreshOpp(msg: { vestigeId: number }, session: BackendSession) {

        let roleId = session.get('roleId');
        let serverId = session.get('serverId');

        let { vestigeId } = msg;

        if(!await checkVestige(serverId, vestigeId)) {
            return resResult(STATUS.GVG_VESTIGE_ERR);
        }
        let { configId, period } = getGVGPeriodData();
        if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);
        let groupKey = await getGroupKey(serverId);

        let myVestigeRank = await getMyVestigeRank(configId, groupKey, vestigeId, roleId);
        let refreshCnt = myVestigeRank.refreshCnt||0;
        if(refreshCnt >= GVG.GVG_REFRESH_TIME) return resResult(STATUS.GVG_VESTIGE_REFESH_CNT_MAX);
        
        let oppRanks = refreshVestigeOppRanks(myVestigeRank.rank);
        myVestigeRank = await GVGVestigeRankModel.refreshOpp(roleId, vestigeId, oppRanks );

        let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, myVestigeRank.oppRanks);

        // 返回
        return resResult(STATUS.SUCCESS, { vestigeId, refreshCnt: myVestigeRank.refreshCnt, oppPlayers });
    }

    // 选择对手
    async chooseOpp(msg: { vestigeId: number, roleId: string, rank: number, myRank: number }, session: BackendSession) {

        let roleId = session.get('roleId');
        let roleName = session.get('roleName');
        let serverId = session.get('serverId');
        let guildCode = session.get('guildCode');
        let sid = session.get('sid');
        let { vestigeId, roleId: targetRoleId, rank, myRank } = msg;

        let { configId, period } = getGVGPeriodData();
        if(period != GVG_PERIOD.PREPARE) return resResult(STATUS.GVG_NOT_PREPARE_PERIOD);

        if(!checkFightTime()) return resResult(STATUS.GVG_VESTIGE_TIME_OUT);

        if(!await checkVestige(serverId, vestigeId)) {
            return resResult(STATUS.GVG_VESTIGE_ERR);
        }
        let dicRank = gameData.gvgVestige.get(vestigeId)?.get(rank);
        if(!dicRank) return resResult(STATUS.DIC_DATA_NOT_FOUND);

        let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        // 检查对手排名/自己排名
        if(!checkVestigeRank(myRank, rank)) return resResult(STATUS.GVG_VESTIGE_RANK_ERR);

        const hasItem = await GVGUserItemModel.checkItemCnt(configId, myLeague.leagueCode, roleId, GVG_ITEM.FIGHT_COIN, 1);
        if(!hasItem) return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
        const groupKey = await getGroupKey(serverId);

        let status = await checkVestigeOppStatus(configId, groupKey, vestigeId, roleId, myRank, targetRoleId, rank); // 锁
        if(status != VESTIGE_OPP_STATUS.BATTLE) {
            let oppRanks = refreshVestigeOppRanks(myRank);
            let oppPlayers = await getOppPlayerByRanks(serverId, groupKey, vestigeId, oppRanks);
            return resResult(STATUS.SUCCESS, { status, oppPlayers });
        }

        // 扣征战令
        const costResult = await handleGVGCost(roleId, myLeague.leagueCode, sid, [{ id: GVG_ITEM.FIGHT_COIN, count: 1 }], [], ITEM_CHANGE_REASON.GVG_VESTIGE_START);
        if(!costResult) {
            await GVGVestigeLockModel.releaseLock(groupKey, vestigeId, rank);
            return resResult(STATUS.GVG_ITEMS_NOT_ENOUGH);
        }
        // 获取征战令对应奖励
        const leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, dicRank.battleLeagueReward, dicRank.battleReward, ITEM_CHANGE_REASON.GVG_VESTIGE_START);
        // 消耗征战令的获得活跃
        let active = await addGVGActive(myLeague.leagueCode, roleId, GVG_ACTIVE_TYPE.COST_FIGHT_COIN);
        // 创建rec
        const attackInfo = await generateAttackInfo(roleId, myLeague, myRank);
        const defenseInfo = await generateDefenseInfo(targetRoleId, vestigeId, rank);
        const rec = await GVGVestigeRecModel.createRec(configId, vestigeId, groupKey, dicRank.warId, attackInfo, defenseInfo, leagueGoods);
        const oppDetail = await getOppDetailData(rec);

        checkGVGTask(serverId, roleId, sid, configId, myLeague.leagueCode, TASK_TYPE.GVG_VESTIGE, { count: 1 });
        return resResult(STATUS.SUCCESS, {
            active,
            ...oppDetail
        });
    }

    // 出战界面撤退
    async giveupCheck(msg: { battleCode: string }, session: BackendSession) {
        let roleId = session.get('roleId');
        let { battleCode } = msg;
        // 更新ladderMatchRec
        let rec = await GVGVestigeRecModel.giveup(roleId, battleCode);
        if(rec && rec.defenseInfo) {
            await GVGVestigeLockModel.releaseLock(rec.groupKey, rec.vestigeId, rec.defenseInfo.oldRank);
        }

        return resResult(STATUS.SUCCESS, { 
            status: 0, time: 0,
            leagueGoods: rec.leagueGoods
        });
    }

    // 获取对手具体战场数据
    async getOppData(msg: { battleCode: string }, session: BackendSession) {
        let roleId = session.get('roleId');
        let { battleCode } = msg;

        let rec = await GVGVestigeRecModel.findByBattleCode(battleCode);
        if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.LADDER_REC_NOT_FOUND);
        let status = getVestigeRecStatus(rec).status;
        if(status == VESTIGE_STATUS.COMPLETE || status == VESTIGE_STATUS.NO) return resResult(STATUS.LADDER_REC_STATUS_IS_COMPLETE);

        let result = await getOppDetailData(rec);
        return resResult(STATUS.SUCCESS, result);
    }

    // 布完阵开始挑战
    async checkBattle(msg: { battleCode: string, heroes: [{ actorId: number, dataId: number, order: number }] }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const { battleCode, heroes } = msg;

        let rec = await GVGVestigeRecModel.findByBattleCode(battleCode);
        if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.GVG_VESTIGE_REC_NOT_FOUND);
        if(getVestigeRecStatus(rec).status != VESTIGE_STATUS.CHECK) return resResult(STATUS.GVG_VESTIGE_CHECK_BATTLE_STATUS_ERR);
        const { vestigeId, defenseInfo: { oldRank: rank }, warId } = rec;

        for(let { actorId } of heroes) {
            if(isHeroHidden(actorId)) return resResult(STATUS.HERO_IS_HIDDEN);
        }
        let { isOK, heroes: dbHeroes } = await checkBattleHeroesByHid(roleId, heroes.map(cur => cur.actorId));
        if(!isOK) return resResult(STATUS.BATTLE_HERO_NOT_FOUND);
        // 检查武将是否在其他遗迹中使用了
        if(await checkHeroIsUsedInOtherVestige(roleId, vestigeId, heroes)) return resResult(STATUS.GVG_VESTIGE_HERO_USED);

        // 更新锁
        const groupKey = await getGroupKey(serverId);
        let lock = await GVGVestigeLockModel.checkBattleLock(groupKey, vestigeId, rank, roleId);
        if(!lock) return resResult(STATUS.GVG_VESTIGE_CHECK_BATTLE_STATUS_ERR);

        // 向vestigerec保存阵容
        const info = await generateAttackHeroInfo(heroes, dbHeroes);
        rec = await GVGVestigeRecModel.startBattle(battleCode, info.heroes, info.ce);

        // 更新battleRecord
        let warInfo = gameData.war.get(warId);
        await BattleRecordModel.updateBattleRecordByCode(battleCode, {
            $set: { roleId, roleName, battleId: warId, status: 0, warName: warInfo?.gk_name, warType: warInfo?.warType, }
        });

        return resResult(STATUS.SUCCESS, {
            time: Math.floor(rec.battleTime/1000) + GVG.GVG_VESTIGE_BATTLE_COUNTDOWN,
            battleCode: rec.battleCode
        });
    }

    // 挑战结算
    async battleEnd(msg: { battleCode: string, isSuccess: boolean }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const sid = session.get('sid');
        const guildCode = session.get('guildCode');
        const { battleCode, isSuccess } = msg;

        let rec = await GVGVestigeRecModel.findByBattleCode(battleCode);
        if(!rec || rec.attackRoleId != roleId) return resResult(STATUS.GVG_VESTIGE_REC_NOT_FOUND);
        if(getVestigeRecStatus(rec).status != VESTIGE_STATUS.BATTLE) return resResult(STATUS.GVG_VESTIGE_BATTLE_END_STATUS_ERR);
        
        let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let historyData = await GVGVestigeRankModel.findByRole(rec.vestigeId, roleId);
        let historyRank = historyData?.rank||0;
        // 交换排名
        let { isChange, atkData, defData, endTime } = await GVGVestigeRankModel.changeRank(isSuccess, rec.vestigeId, rec.attackInfo, rec.defenseInfo);
        atkData = await updateMyVestigeRank(isChange, atkData, defData, historyRank, rec);
        // 更新vestigeRec
        rec = await GVGVestigeRecModel.battleEnd(battleCode, isSuccess, endTime, atkData?.rank, defData?.rank||(isSuccess?rec.attackInfo.oldRank: rec.defenseInfo.oldRank));
        // 更新锁
        await GVGVestigeLockModel.releaseLock(rec.groupKey, rec.vestigeId, rec.defenseInfo.oldRank);
        // 更新battleRecord
        await BattleRecordModel.updateBattleRecordByCode(battleCode, { $set: { status: isSuccess? 1: 2 } });

        // 取消突破排名奖励
        // let { rewards, leagueRewards } = calBreakGoods(rec.vestigeId, historyRank, atkData.rank);
        // let breakGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueRewards, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_END);

        await saveScoreToRank(rec);
        addVestigeBattleEndRec(rec);

        return resResult(STATUS.SUCCESS, {
            vestigeId: rec.vestigeId, 
            battleCode: rec.battleCode, 
            leagueGoods: rec.leagueGoods,
            rank: atkData.rank, 
            score: gameData.gvgVestige.get(rec.vestigeId)?.get(atkData.rank)?.score??0,
            historyRank: atkData.historyRank,
            ...getVestigeRecStatus(rec),
            oppPlayers: await getOppPlayerByRanks(serverId, rec.groupKey, rec.vestigeId, atkData.oppRanks),
            // breakGoods,
            lineup: atkData.lineup,
            lineupCe: atkData.lineup.reduce((pre, cur) => pre + cur.ce, 0),
        });
    }

    // 获取战报信息
    async getRec(msg: { vestigeId: number }, session: BackendSession) {
        let roleId = session.get('roleId');
        let { vestigeId } = msg;
        let list = await GVGVestigeRecModel.findRec(roleId, vestigeId);
        let result: (GVGVestigeRecUpdate & {rplFileUrl: string})[] = [];
        for(let rec of list) {
            const { attackRoleId, battleCode, hasRpl } = rec;
            const rplFileUrl = battleCode && hasRpl ? getRemoteRplFilePath(attackRoleId, WAR_TYPE.GVG_VESTIGE, battleCode) : '';
            const obj = getVestigeRecStatus(rec);
            if(obj.status == VESTIGE_STATUS.COMPLETE) result.push({ ...rec, endTime: obj.time, rplFileUrl });
        }
        return resResult(STATUS.SUCCESS, {
            list: result,
            rplPrefixUrl: getRemoteRplPrefix(pinus.app.get('env'))
        });
    }

    // 征战中原简单小排行榜
    async getLeagueRank(msg: {}, session: BackendSession) {

        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const guildCode = session.get('guildCode');

        const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let groupKey = await getGroupKey(serverId);
        let serverNames = await getAllServerName();

        const { ranks: leagueRank, myRank: myLeagueRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, true, { groupKey, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode });
        const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, true, { groupKey, day: getDayKeyInfo() }, { roleId }, serverNames);
    
        return resResult(STATUS.SUCCESS, {
            leagueRank, myLeagueRank, memberRank, myMemberRank
        })
    }

    // 联军详细排名
    async getLeagueDetailRank(msg: {}, session: BackendSession) {
        const serverId = session.get('serverId');
        const guildCode = session.get('guildCode');
        const roleId = session.get('roleId');

        const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let groupKey = await getGroupKey(serverId);
        let serverNames = await getAllServerName();
        let { configId } = getGVGPeriodData();

        const { ranks, myRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_LEAGUE, false, { groupKey, day: getDayKeyInfo() }, { leagueCode: myLeague.leagueCode }, serverNames);
        const { ranks: memberRank, myRank: myMemberRank } = await getVestigeRank(REDIS_KEY.GVG_VESTIGE_MEMBER_ALL, false, { groupKey, day: getDayKeyInfo() }, { roleId }, serverNames);

        let yesterdayRank = await GVGVestigeLeagueRankModel.getYesterdayRank(myLeague.leagueCode);
        let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode, roleId);
        let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId);
        let { canReceiveBox, boxPreview } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks);

        return resResult(STATUS.SUCCESS, {
            ranks, myRank,
            memberRank, myMemberRank,
            latestRank: yesterdayRank?.rank||0,
            canReceiveBox, boxPreview
        })
    }

    // 玩家排行
    async getPlayerRank(msg: { vestigeId: number }, session: BackendSession) {
        let roleId = session.get('roleId');
        let serverId = session.get('serverId');

        let { vestigeId } = msg;
        let groupKey = await getGroupKey(serverId);

        let dicRankMap = gameData.gvgVestige.get(vestigeId);
        let serverNames = await getAllServerName();
        let vestigeRanks = await GVGVestigeRankModel.findRankByVestige(groupKey, vestigeId);
        let r = new Rank(REDIS_KEY.GVG_VESTIGE_MEMBER, { groupKey, vestigeId });
        let ranks: VestigeRank[] = [], myRank: VestigeRank;
        for(let { roleId: targetRoleId, rank, lineup } of vestigeRanks) {
            let param = <RoleRankInfo>await r.getParam(rank, targetRoleId, [rank]);
            if(!param) {
                let role = await RoleModel.findByRoleId(targetRoleId, ROLE_SELECT.RANK);
                await r.generParamAndSet(REDIS_KEY.USER_INFO, { roleId: targetRoleId }, { role });
                param = <RoleRankInfo>await r.getParam(rank, targetRoleId, [rank]);
            }
            let lineupCe = lineup.reduce((pre, cur) => pre + cur.ce, 0);
            let serverName = serverNames[param.serverId];
            let score = dicRankMap?.get(param.rank)?.score||0;

            let obj = new VestigeRank();
            obj.setByRankParam(param, serverName, lineupCe, score);
            if(obj.roleId == roleId) myRank = obj;
            ranks.push(obj);
        }
        if(!myRank) {
            let obj = new VestigeRank();
            let role = await RoleModel.findByRoleId(roleId, ROLE_SELECT.RANK);
            obj.setByRole(role, serverNames[serverId]);
            myRank = obj;
        }
        return resResult(STATUS.SUCCESS, {
            vestigeId,
            ranks, myRank
        })

    }

    // 领取排行榜获得的每日奖励
    async receiveBox(msg: { }, session: BackendSession) {
        const guildCode = session.get('guildCode');
        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const sid = session.get('sid');

        const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let { configId } = getGVGPeriodData();
        let canReceiveLeagueRanks = await GVGVestigeLeagueRankModel.getCanReceiveRanks(configId, myLeague.leagueCode, roleId);
        let canReceivePlayerRanks = await GVGVestigeSumRankModel.getCanReceiveRanks(configId, roleId);
        if(canReceiveLeagueRanks.length <= 0 && canReceivePlayerRanks.length <= 0) return resResult(STATUS.GVG_RECEIVE_NO_RANK_REWARD);
        
        let { leagueReward, rewards } = calVestigeLeagueBoxRewards(canReceiveLeagueRanks, canReceivePlayerRanks);
        let leagueGoods = await addGVGReward(roleId, roleName, myLeague.leagueCode, sid, leagueReward, rewards, ITEM_CHANGE_REASON.GVG_VESTIGE_RECEIVE_RANK);
        await GVGVestigeLeagueRankModel.receiveRanks(canReceiveLeagueRanks.map(cur => cur._id), roleId);
        await GVGVestigeSumRankModel.receiveRanks(canReceivePlayerRanks.map(cur => cur._id));

        return resResult(STATUS.SUCCESS, {
            leagueGoods,
            canReceiveRanks: false
        })
    }

    async debugCalRec(msg: { battleCode: string }, session: BackendSession) {
        let rec = await GVGVestigeRecModel.findByBattleCode(msg.battleCode);
        await saveScoreToRank(rec);
        return resResult(STATUS.SUCCESS);
    }

    async debugSaveScore(msg: {}, session: BackendSession) {
        await saveVestigeRankSchedule();
        return resResult(STATUS.SUCCESS);
    }

    async debugSetMyRank(msg: { vestigeId: number, rank: number }, session: BackendSession) {
        const { vestigeId, rank } = msg;

        let roleId = session.get('roleId');
        let serverId = session.get('serverId');
        let guildCode = session.get('guildCode');

        let groupKey = await getGroupKey(serverId);
        let { configId } = getGVGPeriodData();

        const myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
        if(!myLeague) return resResult(STATUS.GVG_LEAGUE_NOT_EXIST);

        let myData = await getMyVestigeRank(configId, groupKey, vestigeId, roleId, myLeague)
        let myRank = myData?.rank||0;

        let targetData = await GVGVestigeRankModel.findByRank(configId, groupKey, vestigeId, rank);
        if(targetData) {
            myData = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { rank, oldRank: myRank, historyRank: rank });
            targetData = await GVGVestigeRankModel.updateByRoleId(vestigeId, targetData.roleId, { rank: myRank, oldRank: rank });
        } else {                    
            myData = await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { rank, oldRank: myRank, historyRank: rank });
        }
        await savePlayerRank(configId, groupKey, vestigeId, { isRobot: false, newRank: rank, oldRank: myRank, roleId, leagueCode: myLeague.leagueCode });
        if(targetData) {
            await savePlayerRank(configId, groupKey, vestigeId, { isRobot: false, newRank: targetData.rank, oldRank: rank, roleId: targetData.roleId, leagueCode: targetData.leagueCode });
        }

        return resResult(STATUS.SUCCESS);
    }

    async debugSetMyOpp(msg: { vestigeId: number, oppRanks: number[] }, session: BackendSession) {
        const { vestigeId, oppRanks } = msg;
        let roleId = session.get('roleId');       
        await GVGVestigeRankModel.updateByRoleId(vestigeId, roleId, { oppRanks });
        return resResult(STATUS.SUCCESS);
    }
}