import { ResGetList } from '../protocols/hero/PtlGetList';
import { player } from '../protocols/user/type';
import { EquipShared } from './equip';
import HeroSkinShared from './heroskin';
import { PeijianShared } from './peijian';
import { PlayerShared } from './player';
import { PublicShared } from './public';
import { ShiwuShared } from './shiwu';

export type otherBuff = Partial<player & {
    allBuff: k_v<number>;
}>;
type heroDataType = Partial<Omit<ResGetList['list'][''], 'getTime'>>;

export class HeroShared {
    static getAllBuff(hero: heroDataType[]) {
        let allBuff: k_v<number> = {};

        hero.forEach(h => {
            let heroConf = G.gc.hero[h.heroId];
            let heroGrow = G.gc.herogrow[heroConf.jjup]?.[h.jieji];
            heroGrow && PublicShared.mergeProperty(allBuff, heroGrow.jj_allattr || {});
        });

        return allBuff;
    }

    /**
     * 获取英雄基本属性
     * @param hero 英雄数据
     * @param otherBuff 有些功能会对英雄有属性加成
     */
    static getHeroBasicAttr(hero: heroDataType, otherBuff: otherBuff = G.otherBuff, pos = 0) {
        let jiban = 0;
        let buff: k_v<any> = { skillArr: [] };
        let heroConf = G.gc.hero[hero.heroId];
        let heroLv = G.gc.herolv[heroConf.lvup];
        let heroGrow = G.gc.herogrow[heroConf.jjup]?.[hero.jieji];

        //计算等级属性
        for (let k in heroLv.buff) {
            let val = heroLv.buff[k];
            if (typeof val == 'number') buff[k] = val;
            else buff[k] = PublicShared.eval(val, { lv: hero.lv });
            // else buff[k] = Math.floor(new Function(`let lv=${hero.lv}; return ${val}`)());
        }

        //计算阶级属性
        if (heroGrow) {
            PublicShared.mergeProperty(buff, heroGrow.buff);
            PublicShared.mergeProperty(buff, heroGrow.jj_attr);
        }

        if (pos > 0 && otherBuff.allBuff) {
            PublicShared.mergeProperty(buff, otherBuff.allBuff);
        }

        if (pos > 0) {
            if (otherBuff.headFrames) {
                for (let [id, time] of Object.entries(otherBuff.headFrames)) {
                    if (time == -1 || time > G.time) {
                        PublicShared.mergeProperty(buff, G.gc.playerHeadFrame[id].buff);
                    }
                }
            }

            if (otherBuff.chatFrames) {
                for (let [id, time] of Object.entries(otherBuff.chatFrames)) {
                    if (time == -1 || time > G.time) {
                        PublicShared.mergeProperty(buff, G.gc.playerChatFrame[id].buff);
                    }
                }
            }

            if (otherBuff.model) {
                for (let [id, item] of Object.entries(otherBuff.model)) {
                    if (item.time == -1 || item.time > G.time) {
                        PublicShared.mergeProperty(buff, G.gc.playerModel[id].buff);
                    }
                }
            }
        }

        //计算装备属性
        if (hero.equip) {
            for (let pos in hero.equip) {
                hero.equip[pos] && PublicShared.mergeProperty(buff, EquipShared.getEquipBuff(hero.equip[pos]));
            }

            let equips = Object.values(hero.equip).filter(e => e != '').map(e => EquipShared.fmtEquip(e));

            //计算装备大师属性
            if (equips.length >= 4) {
                let minLv = Math.min(...equips.map(e => e.lv));
                let minStar = Math.min(...equips.map(e => e.star));
                let minAdjustment = Math.min(...equips.map(e => e.adjustment));
                let lvMasterConf = G.gc.equipMaster.peiyang.filter(c => c.aLv <= minLv).sort((a, b) => b.lv - a.lv)[0];
                let starMasterConf = G.gc.equipMaster.shengxing.filter(c => c.aLv <= minStar).sort((a, b) => b.lv - a.lv)[0];
                let adjustmentMasterConf = G.gc.equipMaster.tiaojiao.filter(c => c.aLv <= minAdjustment).sort((a, b) => b.lv - a.lv)[0];

                lvMasterConf && PublicShared.mergeProperty(buff, lvMasterConf.buff);
                starMasterConf && PublicShared.mergeProperty(buff, starMasterConf.buff);
                adjustmentMasterConf && PublicShared.mergeProperty(buff, adjustmentMasterConf.buff);
            }

            //计算装备套装属性
            let ids = equips.map(e => G.gc.equip[e.equipId].tzid).filter(i => !!i).map(i => Object.fromEntries([[i, 1]]));
            let objs: k_v<number> = {};
            ids.forEach(v => PublicShared.mergeProperty(objs, v));

            for (let [id, num] of Object.entries(objs)) {
                let conf = G.gc.equipSuit[id];
                let nums = Object.keys(conf.buff).map(n => Number(n)).sort((a, b) => a - b);
                if (num < nums[0]) continue;
                nums.forEach(n => num >= n && PublicShared.mergeProperty(buff, conf.buff[n]));
            }

            //计算装备羁绊
            let confs = G.gc.group.equip.filter(c => c.page == hero.heroId);
            let equipIds = equips.map(e => e.equipId);
            confs.forEach(conf => {
                if (equipIds.includes(conf.member.toString())) {
                    jiban++;
                    PublicShared.mergeProperty(buff, conf.skill);
                }
            });
        }

        //计算配件属性
        if (hero.peijian) {
            let suitObj: k_v<{ num: number, minLv: number; }> = {};
            let pjs = Object.values(hero.peijian).filter(s => !!s).map(s => PeijianShared.fmt(s));


            pjs.forEach(p => {
                PublicShared.mergeProperty(buff, PeijianShared.getAttr(p));
                let conf = G.gc.peijian[p.peijianId];
                if (conf.suit) {
                    if (!suitObj[conf.suit]) suitObj[conf.suit] = { num: 0, minLv: 0 };
                    suitObj[conf.suit].num++;
                    if (!suitObj[conf.suit].minLv || p.lv < suitObj[conf.suit].minLv) suitObj[conf.suit].minLv = p.lv;
                }
            });

            let sumLv = R.sum(pjs.map(i => i.lv))

            for (let [suitId, data] of Object.entries(suitObj)) {

                // //计算配件套装属性
                // let suitConf = G.gc.peijian_suit[suitId];
                // let suitBuff = Object.entries(suitConf.buff).filter(v => Number(v) <= data.num);
                // suitBuff.forEach(b => PublicShared.mergeProperty(buff, b[1]));

                //计算配件大师属性
                let masterConf = Object.values(G.gc.peijian_master[suitId]).filter(c => c.needLv <= sumLv).sort((a, b) => b.lv - a.lv)[0];
                if (masterConf) {
                    let masterbuff = Object.entries(masterConf.buff).filter(v => Number(v[0]) <= data.num);
                    masterbuff.forEach(b => PublicShared.mergeProperty(buff, b[1]));
                }
            }
        }

        //计算专属武器属性
        if (hero.weapon?.jieji) {
            PublicShared.mergeProperty(buff, G.gc.zhuanshu[heroConf.zhuanshu][hero.weapon.jieji][hero.weapon.star].buff);
        }

        //计算天赋属性
        if (hero.talent) {
            for (let [type, lv] of Object.entries(hero.talent)) {
                let conf = G.gc.hero_tf[type]?.[lv];
                conf && conf.effect && PublicShared.mergeProperty(buff, conf.effect);
            }
        }

        //计算饰物属性
        if (hero.shiwu) {
            for (let pos in hero.shiwu) {
                hero.shiwu[pos] && ShiwuShared.getShiwuBuff(hero.shiwu[pos], buff, hero.heroId);
            }
        }

        //计算潜能属性
        if (hero.qiannneg) {
            for (let type in hero.qiannneg) {
                // console.log(PublicShared.mergeProperty(buff, G.gc.hero_qianneng[type]?.[hero.qiannneg[type]].buff))
                for (let i = 1; i <= hero.qiannneg[type]; i++) {
                    G.gc.hero_qianneng[type]?.[i] && PublicShared.mergeProperty(buff, G.gc.hero_qianneng[type]?.[i].buff);
                }
            }
        }

        //计算名望加成属性
        // if (otherBuff?.renown) {
        //     for (let lv = 1; lv < otherBuff.renown; lv++) {
        //         G.gc.mw_dj[lv].buff && PublicShared.mergeProperty(buff, G.gc.mw_dj[lv].buff);
        //     }
        // }

        //计算维修厂buff
        // if (otherBuff?.wxcLv) {
        //     let curWxcLv = otherBuff.wxcLv.lv + 1;
        //     for (let lv = 1; lv < curWxcLv; lv++) {
        //         PublicShared.mergeProperty(buff, Object.values(G.gc.weixiuchang_zz[lv].buff));
        //         G.gc.weixiuchang_zz[lv].buff2 && PublicShared.mergeProperty(buff, G.gc.weixiuchang_zz[lv].buff2);
        //     }
        //     if (otherBuff.wxcLv.ids.length > 0) {
        //         otherBuff.wxcLv.ids.forEach(id => {
        //             G.gc.weixiuchang_zz[curWxcLv].buff[id + 1] && PublicShared.mergeProperty(buff, G.gc.weixiuchang_zz[curWxcLv].buff[id + 1]);;
        //         });
        //     }
        // }

        //计算收藏品buff;
        if (pos > 0 && otherBuff?.shoucangping) {
            PublicShared.mergeProperty(buff, PlayerShared.getMingDaoBuff(otherBuff as any, 'hero_buff') || {});

            for (let [id, lv] of Object.entries(otherBuff.shoucangping)) {
                if (lv >= 1) {
                    PublicShared.mergeProperty(buff, G.gc.mingdao[id].buff);
                    PublicShared.mergeProperty(buff, Object.fromEntries(Object.keys(G.gc.mingdao[id].upBuff).map(k => [k, G.gc.mingdao[id].upBuff[k] * (lv - 1)])));
                }
            }
        }

        //计算公会物资buff
        if (otherBuff?.ghwz) {
            for (let id in otherBuff.ghwz) {
                let conf = G.gc.shili_wz[id][otherBuff.ghwz[id]];
                conf && PublicShared.mergeProperty(buff, conf.buff);
            }
        }

        //计算阵型加成
        if (pos > 0 && otherBuff?.selectMatrix) {
            let lv = otherBuff.matrix[otherBuff.selectMatrix];
            let select = otherBuff.selectMatrix;
            let posObj = otherBuff.matrixPos?.[select] || {};
            let find = Object.entries(posObj).find(v => v[1] == hero._id);

            if (find) {
                let maxLv = R.values(G.gc.fightPlan[select]).length - 1
                let fixLv = lv > maxLv ? maxLv : lv
                let __buff = G.gc.fightPlan[select][fixLv].buff[Number(find[0]) - 1];
                __buff && PublicShared.mergeProperty(buff, __buff);
            }
        }

        //计算助战属性
        if (pos > 0 && otherBuff?.helpHeros) {
            let arr = otherBuff.helpHeros.map(v => v.jieji);
            let allJieJi = arr.length > 0 ? arr.reduce((a, b) => a + b) : 0;
            let helpBuff = G.gc.herocom.zhuzhanBuff.filter(v => v.need <= allJieJi).sort((a, b) => b.need - a.need)[0];
            helpBuff && PublicShared.mergeProperty(buff, helpBuff.value);
        }

        //计算英雄羁绊
        if (otherBuff?.fightHeros) {
            if (!otherBuff.heroPos || Object.values(otherBuff.heroPos).includes(hero._id)) {
                let confs = G.gc.group.hero.filter(c => c.page == hero.heroId);
                confs.forEach(conf => {
                    let arr = conf.member.split(',').removeOne(id => id == hero.heroId).sort();
                    let inArr = arr.intersection([].concat(otherBuff.fightHeros, otherBuff.helpHeros?.map(h => h.heroId || ''))).sort();

                    if (arr.join('_') == inArr.join('_')) {
                        jiban++;
                        PublicShared.mergeProperty(buff, conf.skill);
                    }
                });
            }
        }

        //计算训练计划
        if (otherBuff?.skills) {
            for (let [id, lv] of Object.entries(otherBuff.skills)) {
                if (lv && G.gc.xunlianjihua[id].use == 0) {
                    PublicShared.mergeProperty(buff, Object.fromEntries([G.gc.xunlianjihua[id].skill].map(k => [k, PublicShared.eval(G.gc.xunlianjihua[id].v[0], { slv: lv })])));
                }
            }
        }

        // 计算皮肤buff
        if (otherBuff?.heroskin) {
            for (let skinId in otherBuff.heroskin) {
                let skinConf = G.gc.heroSkin[skinId];
                if (skinConf.heroId != hero.heroId) console;
                PublicShared.mergeProperty(buff, HeroSkinShared.calcBuff(
                    skinId, otherBuff.heroskin[skinId]
                ));
            }
        }

        //最后进行加成属性计算
        for (let k in buff) {
            if (k.indexOf('pro') == -1) continue;
            let buffKey = k.replace('pro', '');
            if (buff[buffKey]) {
                buff[buffKey] += buff[buffKey] * buff[k];
                if (buffKey == 'baoshang' && buff[buffKey] > 10) buff[buffKey] = 10
                // buff[k] = 0;
            }
        }

        buff.mindps += buff.atk;
        buff.maxdps += buff.atk;

        //属性取整
        this.amendAttr(buff);

        buff.jiban = jiban;
        buff.maxHp = buff.hp;

        return buff;
    };

    /**修正属性 数值取整*/
    static amendAttr(buff: k_v<number>) {
        for (let k in buff) {
            if (typeof buff[k] != 'number') continue;
            if (k.indexOf('pro') != -1 || k.indexOf('drop') != -1) continue;
            buff[k] = Math.floor(buff[k]);
        }
    }

    /**
     * 获取英雄战力
     * @param hero 英雄数据
     * @param otherBuff 有些功能会对英雄有属性加成
     */
    static getHeroZhanLi(hero: heroDataType, otherBuff: otherBuff = G.otherBuff, pos = 0) {
        let buff = this.getHeroBasicAttr(hero, otherBuff, pos);
        return this.computeHeroZhanLi(buff);
    }

    /**
     * 计算英雄战力
     */
    static computeHeroZhanLi(buff: k_v<any> = {}) {
        let atk = buff.atk || 0;
        let mindps = buff.mindps || 0;
        let maxdps = buff.maxdps || 0;
        let def = buff.def || 0;
        let hp = buff.hp || 0;
        let speed = buff.speed || 0;
        let speedpro = buff.speedpro || 0;
        let hppro = buff.hppro || 0;
        let dpspro = buff.dpspro || 0;
        let undpspro = buff.undpspro || 0;
        let xixuepro = buff.xixuepro || 0;
        let baoshangpro = buff.baoshangpro || 0;
        let shanbipro = buff.shanbipro || 0;
        let mingzhongpro = buff.mingzhongpro || 0;
        let pvpdpspro = buff.pvpdpspro || 0;
        let pvpdpsdrop = buff.pvpdpsdrop || 0;

        return Math.floor(
            (atk * .85) +
            (mindps * .85) +
            (maxdps * .75) +
            (def * 1.03) +
            (hp * 1) +
            (hp * hppro * .5) +
            (speed * (speedpro + 1) * 21.28) +
            ((mindps + maxdps) / 2 * dpspro * .75) +
            (hp * undpspro * .6) +
            ((mindps + maxdps) / 2 * xixuepro) +
            ((mindps + maxdps) / 2 * baoshangpro * .75) +
            ((mindps + maxdps) / 2 * shanbipro * .5) +
            ((mindps + maxdps) / 2 * mingzhongpro * .5) +
            ((mindps + maxdps) / 2 * pvpdpspro * .5) +
            (hp * pvpdpsdrop * .5)
        );
    }

    /**
     * 获取英雄升级消耗
     * @param id 英雄id
     * @param lv 英雄等级
     */
    static getHeroLvUpNeed(id: string | number, lv = 1): atn[] {

        return [
            { a: 'item', t: '1', n: G.gc.herolvup[lv].expneed },
            { a: 'attr', t: 'jinbi', n: G.gc.herolvup[lv].jinbineed }
        ];
    }

    /**
     * 获取英雄进阶消耗
     * @param id 英雄id
     * @param lv 英雄当前阶级
     */
    static getHeroJinJieNeed(id: string | number, jieji = 0): atn[] {
        let heroJinJie = G.gc.herogrow[G.gc.hero[id].jjup];
        return heroJinJie?.[jieji + 1]?.need || [];
    }
}