import { ACTIVITY_TYPE, getRedisKeyByRankType, MAIL_TYPE, RANK_TYPE, REDIS_KEY } from "../../consts";
import { ActivityGroupModel } from "../../db/ActivityGroup";
import { ActivityTimeLimitRankModel, ActivityTimeLimitRankModelTypeParam } from "../../db/ActivityTimeLimitRank";
import { GuildModel, GuildType } from "../../db/Guild";
import { RoleModel } from "../../db/Role";
import { TimeLimitRankData } from "../../domain/activityField/timeLimitRankField";
import { GuildRankInfo, RoleRankInfo } from "../../domain/rank";
import { stringWithTypeToRewardInter } from "../../pubUtils/roleUtil";
import { sendMailByContent, sendMailToGuildByContent } from "../mailService";
import { Rank } from "../rankService";
import { getServerCreateTime } from "../redisService";
import { getActivitiesByType, getActivityById } from "./activityService";


/**
   * 玩家活动数据
   *
   * @param {number} serverId 区Id
   * @param {number} activityId 活动Id
   * @param {string} roleId 角色Id
   *
   */
 export async function getTimeLimitRankData(activityId: number, serverId: number) {
    let activityData = await getActivityById(activityId);
    let serverTime = await getServerCreateTime(serverId);

    let playerData = new TimeLimitRankData(activityData, 0, serverTime);
    return playerData;
}

export async function getTimeLimitRankDataShow(activityId: number, serverId: number) {
    let playerData = await getTimeLimitRankData(activityId, serverId);
    if(playerData && playerData.canShow && playerData.canShow()) {
        return playerData.getShowResult();
    }
    return null
}


/**
 * @description 记录每次活动获得的资金排行榜
 * @param serverId 
 * @param code 
 * @param fund 
 */
export async function recordGuildFund(serverId: number, guild: GuildType, fund: number) {
    let activities = await getActivitiesByType(serverId, ACTIVITY_TYPE.TIME_LIMIT_RANK);
    for(let activity of activities) {
        let serverTime = await getServerCreateTime(serverId);
        let playerData = new TimeLimitRankData(activity, 0, serverTime);
        if(playerData.canRecord() && playerData.rankType == RANK_TYPE.GUILD_FUND) {
            await ActivityTimeLimitRankModel.addGuildScore(serverId, playerData.activityId, playerData.rankType, guild.code, fund, guild._id);
            
            let redisKey = getRedisKeyByRankType(playerData.rankType);
            // 加入排行
            let r = new Rank(redisKey, { serverId, activityId: playerData.activityId });
            await r.setRankWithGuildInfo(guild.code, fund, Date.now(), guild, true);
        }
    }
}

/**
 * 活动结束发送排行榜奖励
 * @param data {TimeLimitRankData} 活动数据
 * @returns 
 */
export async function sendRankMail(data: TimeLimitRankData, serverId: number) {
    let redisKey = getRedisKeyByRankType(data.rankType, true);
    if (!redisKey) return null;
    let r = new Rank(redisKey, { activityId: data.activityId, serverId });
    if(r.infoKey == REDIS_KEY.GUILD_INFO) {
        let allRank = <GuildRankInfo[]>(await r.getRankByRange());

        for(let { rank, code, name, leader } of allRank) {
            let reward = data.getRewardByRank(rank);
            if(reward) {
                let guild = await GuildModel.findByCode(code, serverId, '+members');
                // console.log(guild.members)
                for(let roleId of guild.members) {
                    await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, {
                        params: [data.tabName,`${rank}`],
                        goods: stringWithTypeToRewardInter(roleId == leader.roleId? reward.rewards: reward.guildRewards)
                    });
                }
            }
        }
    } else {
        let allRank = <RoleRankInfo[]>(await r.getRankByRange());

        for(let { rank, roleId } of allRank) {
            let reward = data.getRewardByRank(rank);
            if(reward) {
                await sendMailByContent(MAIL_TYPE.TIME_LIMIT_RANK, roleId, {
                    params: [data.tabName, `${rank}`],
                    goods: stringWithTypeToRewardInter(reward.rewards)
                });
            }
        }
    }
}

export async function takeSnapshot(data: TimeLimitRankData, serverId: number) {
    let redisKey = getRedisKeyByRankType(data.rankType);
    let targetRedisKey = getRedisKeyByRankType(data.rankType, true);
    if (!redisKey || !targetRedisKey || redisKey == targetRedisKey) return null;


    let insertInfos: ActivityTimeLimitRankModelTypeParam[] = [];
    let r = new Rank(redisKey, { serverId, activityId: data.activityId });
    let allRank = await r.getRankDataByRankWithoutDetail();
    let targetR = new Rank(targetRedisKey, { serverId, activityId: data.activityId });
    for(let rank of allRank) {
        await targetR.setRank(rank.myId, rank.scores);

        let insertBaseInfo = {
            serverId, activityId: data.activityId, rankType: data.rankType, score: rank.scores[0]||0, time: rank.scores[1]||0
        }
        if(rank.myId.roleId) {
            let role = await RoleModel.findByRoleId(rank.myId.roleId, '_id roleId');
            if(role) insertInfos.push({ ...insertBaseInfo, roleId: role.roleId, role: role._id });
        } else if(rank.myId.guildCode) {
            let guild = await GuildModel.findByCode(rank.myId.guildCode, serverId, '_id guildCode');
            if(guild) insertInfos.push({ ...insertBaseInfo, guildCode: guild.code, guild: guild._id });
        }
    }
    await ActivityTimeLimitRankModel.insertRanks(insertInfos);
}