import { GIFT_PACKAGE_TYPE, ACTIVITY_RESOURCES_TYPE, ITEM_CHANGE_REASON, STATUS } from '../../consts';
import { gameData } from '../../pubUtils/data';
import { addItems } from '../role/rewardService';
import { RewardParam } from '../../domain/activityField/rewardField';
import { CreateHeroParam } from '../../domain/roleField/hero';
import { DicGiftPackage } from '../../pubUtils/dictionary/DicGiftPackage';
import { ItemInter, RewardInter } from '../../pubUtils/interface';
import { decodeArrayListStr, getRandEelmWithWeight, resResult } from '../../pubUtils/util';
import { createHeroes } from '../role/createHero';
import { GuildModel } from '../../db/Guild';
import { pushGuildInfoUpdate } from '../guildService';
import { combineItems } from '../role/util';
import { recordGuildFund } from './timeLimitRankService';
import { filterGoods, isGoodsHidden, isHeroHidden } from '../dataService';
import { DicGiftPackagePlan } from '../../pubUtils/dictionary/DicGiftPackagePlan';
import { Floor, GiftPackageFloorModel } from '../../db/GiftPackageFloor';



/**
 * 兑换礼包
 * @param giftID 礼包id
 * @param roleId 角色id
 * @param roleName 角色名称
 * @param giftCount 一共消耗多少个礼包
 * @param sid 
 */
export async function useGiftPackage(roleId: string, roleName: string, sid: string, serverId: number, guildCode: string, giftID: number, selected: Array<number> = [], giftCount: number) {
    console.log("bbbbbbbb", giftID, selected)
    let result: { goods: {id: number, count: number, seqId?: number, isBag?: boolean}[], addHeros: any[]} = { goods: [], addHeros: [] }
    let giftPackageData = gameData.giftPackage.get(giftID);
    if (!giftPackageData) {
        return resResult(STATUS.SUCCESS, result);
    }
    console.log('dddddddddddddd', giftID, JSON.stringify(giftPackageData))
    let giftType = giftPackageData.type;//礼包类型
    let dicGiftPackagePlan = gameData.giftPackagePlan.get(giftPackageData.id)||[];

    switch (giftType) {
        case GIFT_PACKAGE_TYPE.ALL://全部
            {
                let allReward = [];
                for (let obj of dicGiftPackagePlan) {
                    allReward.push({ type: obj.contentType, id: obj.content, count: obj.count * giftCount });
                }

                result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE);
                break;
            }
        case GIFT_PACKAGE_TYPE.SELECTED_X://手选
            {
                let count = giftPackageData.count;//选择个数
                if (selected.length != count) {
                    break;
                }
                let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content));
                let selectedReward = getSelectedReward(pool, selected)
                let allReward: { type: number, id: number, count: number }[] = [];
                for (let obj of selectedReward) {
                    allReward.push({ type: obj.type, id: obj.id, count: obj.count * giftCount });
                }
                let gids = allReward.filter(cur => cur.type == 2).map(cur => cur.id);
                if(gids.length > 0 && isGoodsHidden(...gids)) return resResult(STATUS.ITEM_IS_HIDDEN);
                let hids = allReward.filter(cur => cur.type == 1).map(cur => cur.id);
                if(hids.length > 0 && isHeroHidden(...gids)) return resResult(STATUS.HERO_IS_HIDDEN);

                result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE);
                break;
            }
        case GIFT_PACKAGE_TYPE.RANDOM_X://随机
            {
                let count = giftPackageData.count;//随机个数
                let pool = dicGiftPackagePlan.filter(cur => cur.contentType == 1? !isHeroHidden(cur.content): !isGoodsHidden(cur.content));
                if(pool.length <= 0) return resResult(STATUS.DIC_DATA_NOT_FOUND);
                let allReward: { type: number, id: number, count: number }[] = [];
                let giftPackage = { giftPackageId: giftID };
                for (let i = 0; i < giftCount; i++) {
                    let { rewards, floors } = await randomSelectedData(pool, roleId, giftID, count);
                    allReward.push(...rewards);
                    giftPackage['floors'] = floors;
                }
                result = await addReward(roleId, roleName, sid, serverId, allReward, ITEM_CHANGE_REASON.USE_GIFT_PACKAGE);
                Object.assign(result, { giftPackage });
                break;
            }
        case GIFT_PACKAGE_TYPE.GUILD_FUND: // 军团资金
            {
                console.log('ccccc',guildCode, giftPackageData.count, giftCount)
                if(!guildCode) return resResult(STATUS.ITEM_CANNOT_RECEIVE_NO_GUILD);
                const guild = await GuildModel.updateInfo(guildCode, {}, { fund: giftPackageData.count * giftCount });
                await pushGuildInfoUpdate(guildCode, { fund: guild.fund });    
                recordGuildFund(serverId, guild, giftPackageData.count * giftCount);    
                break;
            }
        default:
            break;
    }

    return resResult(STATUS.SUCCESS, result);
}

//结算奖励的内容
export async function addReward(roleId: string, roleName: string, sid: string, serverId: number, reward: Array<RewardParam>, reason: number) {
    let giftReward = rewardItemData(reward);
    let goodArray = giftReward.goods;
    let heroArray = giftReward.heroes;

    //兑换物品
    let goods = await addItems(roleId, roleName, sid, goodArray, reason)
    let addHeros = [];
    if (heroArray.length > 0) {
        let heroResult = await createHeroes(roleId, roleName, sid, serverId, heroArray);
        goods = goods.concat(heroResult.goods)
        addHeros = addHeros.concat(heroResult.heroes);
    }

    return { goods: combineItems(goods), addHeros }
}

//表中的奖励数据(包括礼包)转换成具体对应奖励物品的实例
export function rewardItemData(reward: Array<RewardParam>) {
    let goods: Array<RewardInter> = [];
    let heroes: Array<CreateHeroParam> = [];
    for (let obj of reward) {
        switch (obj.type) {
            case ACTIVITY_RESOURCES_TYPE.HERO:
                heroes.push({ hid: obj.id, count: obj.count })
                break;
            case ACTIVITY_RESOURCES_TYPE.GOODS:
                goods.push({ id: obj.id, count: obj.count })
                break;
            case ACTIVITY_RESOURCES_TYPE.GIFTPACKAGE://配置成礼包会立刻兑换，配置成物品会把礼包放入背包中
                let goodData = gameData.goods.get(obj.id);//礼包物品
                let giftPackageData = gameData.giftPackage.get(goodData.gift);//礼包数据
                let giftReward = rewardItemData(giftPackageData.reward)
                goods = goods.concat(giftReward.goods)
                heroes = heroes.concat(giftReward.heroes)
                break;
            default:
                break;
        }
    }
    return { goods, heroes }
}

export function getSelectedReward(plans: DicGiftPackagePlan[], selected: Array<number>): Array<RewardParam> {

    let selectedReward: Array<RewardParam> = [];
    for (let i = 0; i < selected.length; i++) {
        let index = selected[i];
        if (plans.length > index) {
            let { contentType, content, count } = plans[index];
            selectedReward.push({ type: contentType, id: content, count });
        }
    }
    return selectedReward;
}

// 根据是否触发保底，更新抽取次数
function updateFloorCount(floors: Floor[], maxQaulity: number, isTrigger: boolean) {
    for (let floor of floors) {
        if (!isTrigger) {
            floor.count++;
        } else {
            if (floor.quality <= maxQaulity) {
                floor.count = 0;
            } else {
                floor.count++;
            }
        }
    }
    return floors;
}

// 将随机池子根据保底 id 进行分组
function groupByFloorId(plans: DicGiftPackagePlan[]): { [key: number]: DicGiftPackagePlan[] } {
    return plans.reduce((acc, cur) => {
        if (cur.floorId !== 0) {
            if (!acc[cur.floorId]) acc[cur.floorId] = [];
            acc[cur.floorId].push(cur);
        }
        return acc;
    }, {} as { [key: number]: DicGiftPackagePlan[] });
}

// 初始化用户某个礼包的保底数据
async function initFloorData(floors: Floor[], floorPlans: { [key: number]: DicGiftPackagePlan[] }) {
    for (let floorId in floorPlans) {
        let hasFloorFlag = false;
        for (let floor of floors) {
            if (floor.id === parseInt(floorId)) {
                hasFloorFlag = true;
                continue;
            }
        }
        if (!hasFloorFlag) {
            floors.push({ id: parseInt(floorId), count: 0, quality: gameData.giftPackageFloor.get(parseInt(floorId)).quality });
        }
    }
}

async function randomSelectedData(pool: DicGiftPackagePlan[], roleId: string, giftPackageId: number, count: number) {
    let rewards: RewardParam[] = [];
    const floorPlans = groupByFloorId(pool);
    let dropHistory = (floorPlans && Object.keys(floorPlans).length > 0) ? await GiftPackageFloorModel.findByGiftPackageId(roleId, giftPackageId): { floors: [], getSum: 0, allSum: 0 };
    let { floors = [], getSum = 0, allSum = 0 } = dropHistory;

    for (let i = 0; i < count; i++) {
        let randResult = getRandEelmWithWeight(pool)?.dic;
        if (!randResult) continue;
        // 如果没有保底池子，直接返回
        if (!floorPlans || Object.keys(floorPlans).length === 0) {
            rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count });
            continue;
        }

        initFloorData(floors, floorPlans);

        // 检查随机结果的 id 是否在 floorPlans 中，是的话抽中保底
        let flag = false;
        for (let floorId in floorPlans) {
            if (floorPlans[floorId].findIndex(cur => cur.id === randResult.id) !== -1) {
                flag = true;
                break;
            }
        }

        // 检查是否达到了保底次数，并且记录最大品质的 floorId
        let maxQaulityFloorId = 0; // 最大品质的 floorId
        let maxQaulity = 0;
        if (!flag) {
            for (let floor of floors) {
                if (floor.count + 1 >= gameData.giftPackageFloor.get(floor.id).times) {
                    flag = true;
                    if (gameData.giftPackageFloor.get(floor.id).quality > maxQaulity) {
                        maxQaulityFloorId = floor.id;
                        maxQaulity = gameData.giftPackageFloor.get(floor.id).quality;
                    }
                }
            }
        }

        // 更新抽取次数，确定要返回的物品
        if (flag && maxQaulityFloorId == 0) { // 抽到了保底物品
            const quality = gameData.giftPackageFloor.get(randResult.floorId).quality;
            rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count });
            updateFloorCount(floors, quality, true);
            getSum++;
            console.log('got floorId: ', randResult.floorId, quality);
        } else if (flag && maxQaulityFloorId > 0) { // 次数保底
            let floorResult = getRandEelmWithWeight(floorPlans[maxQaulityFloorId])?.dic;
            if (!floorResult) continue;
            rewards.push({ type: floorResult.contentType, id: floorResult.content, count: floorResult.count });
            updateFloorCount(floors, maxQaulity, true);
            getSum++;
            console.log('got floorId: ', maxQaulityFloorId, maxQaulity);
        } else { // 未达到保底次数
            rewards.push({ type: randResult.contentType, id: randResult.content, count: randResult.count });
            updateFloorCount(floors, 0, false);
            console.log('got floorId: ', randResult.floorId, 0);
        }
        allSum++;
    }

    let result;
    result = Object.assign({}, { rewards })
    if(floorPlans && Object.keys(floorPlans).length > 0) {
        const { floors: newFloors } = await GiftPackageFloorModel.updateByGiftPackageId(roleId, giftPackageId, {
            floors, getSum, allSum
        });
        Object.assign(result, { giftPackageId, floors: newFloors });
    }
    return result;
}

//数据格式转换'类型&id&数量|类型&id&数量|' ->> Array<RewardParam> 活动奖励
export function stringToRewardParam(rewardStr: string): Array<RewardParam> {
    let result = new Array<{ type: number, id: number, count: number }>();
    if (!rewardStr) return result;
    let decodeArr = decodeArrayListStr(rewardStr);
    for (let [type, id, count] of decodeArr) {
        if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) {
            continue;
        }
        result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) });
    }
    return result
}

//数据格式转换'类型&id&数量|类型&id&数量|' ->> Array<ItemInter> 资源消耗
export function stringToConsumeParam(...rewardStrs: string[]) {
    let result = new Array<{ type: number, id: number, count: number }>();
    for(let rewardStr of rewardStrs) {
        if(!rewardStr) continue;
        let decodeArr = decodeArrayListStr(rewardStr);
        for (let [type, id, count] of decodeArr) {
            if (isNaN(parseInt(type)) || isNaN(parseInt(id)) || isNaN(parseInt(count))) {
                throw new Error('data table format wrong');
            }
            result.push({ type: parseInt(type), id: parseInt(id), count: parseInt(count) });
        }
    } 
    return combineItems(result);
}

//数据格式转换'id&数量|id&数量|' ->> Array<RewardInter> 老资源格式
export function stringToRewardInter(rewardStr: string): Array<RewardInter> {
    let result = new Array<{ id: number, count: number }>();
    if (!rewardStr) return result;
    let decodeArr = decodeArrayListStr(rewardStr);
    for (let [type, id, count] of decodeArr) {
        if (isNaN(parseInt(id)) || isNaN(parseInt(count))) {
            throw new Error('data table format wrong');
        }
        result.push({ id: parseInt(id), count: parseInt(count) });
    }
    return result
}
