import { Application, BackendSession, ChannelService } from 'pinus';
import { resResult, getRandEelm, shouldRefresh, sortArrRandom } from '../../../pubUtils/util';
import { STATUS, GUILD_OPERATE, GUILD_AUTH, GUILD_JOB, GUILD_APPLY_TYPE, GUILD_STRUCTURE, GUILD_REC_TYPE, GUILD_STRUCTURE_NAME, MAIL_TYPE, REDIS_KEY, GUILD_SELECT, USER_GUILD_SELECT, TASK_TYPE } from '../../../consts';
import { UserGuildModel, UserGuildType } from '../../../db/UserGuild';
import { checkAuth, joinGuild, getGuildWithRefActive, getUserGuildWithRefActive, addActive, settleGuildWeekly, getMyGuildInfo } from '../../../services/guildService';
import { GuildModel, GuildType } from '../../../db/Guild';
import { RoleModel, RoleType } from '../../../db/Role';
import { ARMY } from '../../../pubUtils/dicParam';
import { handleCost, addItems } from '../../../services/rewardService';
import { getGoldObject } from '../../../pubUtils/itemUtils';
import { nowSeconds, getTimeFun } from '../../../pubUtils/timeUtil';
import { GuildListInfo } from '../../../domain/battleField/guild';
import { GuildLeader } from '../../../domain/rank';
import { UserGuildApplyModel } from '../../../db/UserGuildApply';
import { hasStructureConsume, getStructureConsume, gameData } from '../../../pubUtils/data';
import { GuildRecModel } from '../../../db/GuildRec';
import { sendMailByContent, SendMailFun } from '../../../services/mailService';
import {  updateUserInfo, isRoleOnline, getRoleOnlineInfo } from '../../../services/redisService';

import { openGuildRefine } from '../../../services/guildRefineService'; 
import { unlockTrain } from '../../../services/guildTrainService';
import { removeBossRank } from '../../../services/guildBossService';
import { removeTrainRank } from '../../../services/guildTrainService';
import { pushGuildNoticeUpdateMsg, pushGuildUpStructureMsg, addRoleToGuildChannel, getGuildChannelSid } from '../../../services/chatService';
import { Rank } from '../../../services/rankService';
import { checkTask } from '../../../services/taskService';
export default function (app: Application) {
    return new GuildHandler(app);
}

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

    // 创建军团
    async createGuild(msg: { name: string, icon: number, notice: string }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const sid = session.get('sid');
        const serverId = session.get('serverId');
        const { name, icon, notice } = msg;

        // 检查权限是否够，包括是否参过团
        const checkResult = await checkAuth(GUILD_OPERATE.CREATE_GUILD, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        // 检查名字是否重
        const checkNameResult = await GuildModel.checkName(name, serverId);
        if(checkNameResult) return resResult(STATUS.GUILD_NAME_DUP);

        // 检查元宝是否够
        const role = await RoleModel.findByRoleId(roleId);
        if(ARMY.ARMY_CREAT_COST > role.gold) {
            return resResult(STATUS.DAILY_REFRESH_GOLD_LACK);
        }

        await handleCost(roleId, sid, [getGoldObject(ARMY.ARMY_CREAT_COST)]);

        // 创建公会
        const guild = await GuildModel.createGuild({ name, icon, notice }, role, serverId);
        if(!guild) return resResult(STATUS.GUILD_CREATE_ERROR);
        guild.leader = <RoleType>guild.leader;
        //创建科技树
        await openGuildRefine(guild.code);
        await unlockTrain(guild.code, 1);
        const userGuild = await UserGuildModel.createUserGuild(guild.code, role, true);
        if(!userGuild) return resResult(STATUS.GUILD_CREATE_ERROR);

        await RoleModel.joinGuild(roleId, guild.code, guild.name);
        await UserGuildApplyModel.deleteApply(roleId); // 删除玩家所有对其他公会的申请

        // 加入排行
        let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId});
        await r.setRankWithGuildInfo(guild.code, 0, Date.now(), guild);
        let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, {serverId});
        await r2.setRankWithGuildInfo(guild.code, 0, Date.now(), guild);

        let rank = await r.getMyRank({ guildCode: guild.code });

        // 加入channel
        session.set('guildCode', guild.code);
        session.push('guildCode', () => {});
        addRoleToGuildChannel(roleId, sid, guild.code);

        // 添加动态
        const rec = await GuildRecModel.createGuildRec(roleId, guild.code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]);
        let chatSid = await getGuildChannelSid(guild.code);
        this.app.rpc.chat.guildRemote.addRec.toServer(chatSid, rec);

        // 返回
        const result = { ...guild, rank, myInfo: { ...userGuild, isOnline: true}};
        return resResult(STATUS.SUCCESS, result);
    }

    // 获取军团列表
    async getGuildList(msg: { page: number, showPeopleMax: boolean, name: string }, session: BackendSession) {
        
        const roleId = session.get('roleId');
        // const sid = session.get('sid');
        const serverId = session.get('serverId');
        const { page = 1, showPeopleMax, name } = msg;

        const checkResult = await checkAuth(GUILD_OPERATE.GET_GUILD_LIST, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guildList = await GuildModel.findByCondition(page, showPeopleMax, name, serverId);
        const applyList = await UserGuildApplyModel.findApplyByRole(roleId);

        const { quitGuildTime: quitTime = 0 } = await RoleModel.findByRoleId(roleId);

        const list = new Array<GuildListInfo>(); 
        for(let guild of guildList) {
            let info = new GuildListInfo(guild);

            let hasApply = applyList.find(cur => cur.guildCode == guild.code);
            info.setApply(!!hasApply);
            list.push(info);
        }
        return resResult(STATUS.SUCCESS, { quitTime, list });
    }

    // 团长修改军团名等信息
    async setGuildInfo(msg: { code: string, name: string, notice: string, introduce: string, ceLimit: number, isAuto: boolean }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const { code, name, notice, introduce, ceLimit, isAuto } = msg;
        if(!name) return resResult(STATUS.WRONG_PARMS);

        const checkResult = await checkAuth(GUILD_OPERATE.SET_INFO, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const select = ['code', 'name', 'notice', 'introduce', 'ceLimit', 'isAuto', 'icon'];
        const guild = await GuildModel.updateInfo(code, { name, notice, introduce, ceLimit, isAuto }, {}, select.join(' '));
        let chatSid = await getGuildChannelSid(code);
        this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { name, notice, introduce, ceLimit, isAuto });

        await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{ field: 'name', value: name }]);
        if (notice) {
            pushGuildNoticeUpdateMsg(roleId, roleName, guild);
        }
        // 返回
        return resResult(STATUS.SUCCESS, { ...guild });
    }
    
    // 游客查看军团详细信息
    async getGuildInfo(msg: { code: string }, session: BackendSession) {

        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const { code } = msg;

        const checkResult = await checkAuth(GUILD_OPERATE.GET_GUILD_INFO, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const select = ['code', 'name', 'notice', 'ceLimit', 'isAuto', 'icon', 'lv', 'memberCnt', 'guildCe'];
        const guild = await GuildModel.findByCode(code, serverId, select.join(' '));
        let leader = <RoleType>guild.leader;
        delete guild.leader;
        // 返回
        return resResult(STATUS.SUCCESS, { ...guild, leader: leader.roleName });
    
    }

    // 团长授权头衔
    async setAuth(msg: { roleId: string, auth: number }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const { roleId: memberRoleId, auth } = msg;

        const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode');
        const hisUserGuild = await UserGuildModel.getMyGuild(memberRoleId, 'auth guildCode job');

        const checkMyResult = await checkAuth(GUILD_OPERATE.SET_AUTH, roleId, null, myUserGuild);
        if(!checkMyResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const checkResult = await checkAuth(GUILD_OPERATE.BE_SET_AUTH, memberRoleId, myUserGuild.guildCode, hisUserGuild);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const { guildCode: code } = myUserGuild;

        if(auth == hisUserGuild.auth) {
            return resResult(STATUS.GUILD_AUTH_NOT_CHANGE);
        }

        // 管理员最大数 等策划表
        let guild = await GuildModel.findByCode(code, serverId, 'managerCnt lv');
        if(!guild) {
            return resResult(STATUS.GUILD_NOT_FOUND);
        }

        let managerCntInc = 0;
        if(auth == GUILD_AUTH.LEADER) { // 转让团长
            if(hisUserGuild.auth == GUILD_AUTH.MANAGER) {
                managerCntInc = -1;
            }
         } else {
            managerCntInc = auth == GUILD_AUTH.MANAGER? 1: -1;
        }

        let maxManagerCnt = gameData.centerBase.get(guild.lv);
        if(!maxManagerCnt) return STATUS.DIC_DATA_NOT_FOUND;

        if(guild.managerCnt + managerCntInc > maxManagerCnt.managerNum) {
            return resResult(STATUS.GUILD_MANAGER_REACH_MAX);
        }

        const userGuild = await UserGuildModel.updateInfo(memberRoleId, { auth, job: auth == GUILD_AUTH.LEADER? GUILD_JOB.JIANGJUN: hisUserGuild.job }, {}, 'auth'); // 设置权限
        if(!userGuild) {
            return resResult(STATUS.GUILD_MEMBER_NOT_FOUND);
        }

        const role = await RoleModel.findByRoleId(memberRoleId);
        let updateObject = {};
        if(auth == GUILD_AUTH.LEADER) { // 转让团长
            updateObject['leader'] = role._id;
            await UserGuildModel.updateInfo(roleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}); // 自己降权限
            await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(role) } ]);
        }

        guild = await GuildModel.updateInfo(code, updateObject, { managerCnt: managerCntInc }, 'managerCnt code name'); // 如果有转让团长设置leader
        let chatSid = await getGuildChannelSid(code);

        // 添加动态
        if(auth == GUILD_AUTH.MANAGER) {
            const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.SET_MANAGER, [role.roleName]);
            this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { managerCnt: guild.managerCnt });
            this.app.rpc.chat.guildRemote.addRec.toServer(chatSid, rec);
            await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_MANAGER, memberRoleId, { sendName: roleName, params: [guild.name] });
        } else if (auth == GUILD_AUTH.LEADER) {
            const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.SET_LEADER, [roleName, role.roleName]);
            this.app.rpc.chat.guildRemote.changeLeader.toServer(chatSid, code, guild.managerCnt, role, roleId);            
            this.app.rpc.chat.guildRemote.addRec.toServer(chatSid, rec);            
            await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, memberRoleId, { sendName: roleName, params: [guild.name] });
        } else {
            this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid,code, { managerCnt: guild.managerCnt });
            await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_MEMBER, memberRoleId, { sendName: roleName, params: [guild.name] });
        }


        // 返回
        return resResult(STATUS.SUCCESS, { 
            roleId: memberRoleId, auth: userGuild.auth, managerCnt: guild.managerCnt
         });
    
    }

    // 团员获取自己军团详细信息
    async getMyGuildInfo(msg: { }, session: BackendSession) {

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

        let userGuild = await getUserGuildWithRefActive(roleId, 'job auth guildCode receivedActive activeRecord activeDaily activeWeekly');
        if(!userGuild) {
            return resResult(STATUS.SUCCESS, { hasGuild: false })
        };

        const checkResult = await checkAuth(GUILD_OPERATE.GET_MY_GUILD_INFO, roleId, userGuild.guildCode, userGuild);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);
        
        let guild = await getGuildWithRefActive(userGuild.guildCode, serverId);
        if(!guild) {
            return resResult(STATUS.GUILD_NOT_FOUND);
        }

        let result = await getMyGuildInfo(roleId, sid, userGuild, guild, serverId, session);
        return resResult(STATUS.SUCCESS, result);
    }

    // 玩家申请公会
    async applyGuild(msg: { code: string }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const sid = session.get('sid');
        const { code } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.APPLY_GUILD, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await GuildModel.findByCode(code, serverId);
        if(!guild) return resResult(STATUS.GUILD_NOT_FOUND);

        const { isMemberMax, isAuto, ceLimit, lv } = guild;
        if(isMemberMax) {
            return resResult(STATUS.GUILD_MEMBER_MAX);
        }

        const role = await RoleModel.findByRoleId(roleId, null, true);
        if(ceLimit > role.ce) {
            return resResult(STATUS.GUILD_NOT_REACH_CONDI);
        }
        // TODO 暂时关闭
        // if(nowSeconds() - role.quitGuildTime < 3600) { // TODO 时间系统参数表配置
        //     return resResult(STATUS.GUILD_QUIT_TIME);
        // }

        let hasGuild = false;
        if(isAuto) { // 自动加入
            const joinResult = await joinGuild(code, guild.name, lv, roleId, serverId, session);
            if(joinResult.status == -1) {
                return joinResult.resResult;
            }

            // 添加动态
            const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [roleName]);
            // 更新人数增加
            let chatSid = await getGuildChannelSid(code);

            this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe });
            this.app.rpc.chat.guildRemote.addRec.toServer(chatSid,rec);
            hasGuild = true;
        } else { // 不自动加入，插入申请表
            await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.APPLY);
        }

        // 返回
        return resResult(STATUS.SUCCESS, { code, hasGuild });
    }

    // 玩家申请公会
    async getApplyList(msg: { code: string, lastApplyCode: string }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const { code, lastApplyCode } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.GET_APPLY_LIST, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const result = await UserGuildApplyModel.findApplyByGuild(code, lastApplyCode);
        const list = [];
        for(let cur of result) {
            let role = <RoleType>cur.role;
            delete cur.role;
            let isOnline = await isRoleOnline(role.roleId);
            list.push({ applyCode: cur.applyCode, ...role, isOnline });
        }

        return resResult(STATUS.SUCCESS, { list });
    }

    // 团长同意/拒绝公会申请
    async receiveApply(msg: { code: string, applyCodeList: [string], isReceived: boolean }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const { code, applyCodeList, isReceived } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.RECEIVE_APPLY, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const applyList = await UserGuildApplyModel.getListByApplyCode(applyCodeList);

        const guild = await GuildModel.findByCode(code, serverId);
        let roleIds = new Array<string>();
        if(isReceived) { // 同意申请，加入
    
            for(let { roleId } of applyList) {
                const joinResult = await joinGuild(code, guild.name, guild.lv, roleId, serverId, session);
                if(joinResult.status == -1) continue;
                let chatSid = await getGuildChannelSid(code);
                // 更新人数增加
                this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe });
                // 添加动态
                const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [joinResult.roleName]);
                this.app.rpc.chat.guildRemote.addRec.toServer(chatSid,rec);

                roleIds.push(roleId);
            }
        } else { // 拒绝申请，删除申请
            for(let { roleId } of applyList) {
                await sendMailByContent(MAIL_TYPE.GUILD_APPLY_REFUSE, roleId, { sendName: roleName, params: [guild.name] });
            }

            await UserGuildApplyModel.deleteByApplyCode(applyCodeList);
        }

        return resResult(STATUS.SUCCESS, { roleIds });
    }

    // 团长查看（刷新）可邀请人列表
    async getInviteMemberList(msg: { }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');

        let myGuild = await UserGuildModel.getMyGuild(roleId, USER_GUILD_SELECT.ENTRY)
        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.GET_INIVATION_MEMBER_LIST, roleId, myGuild.guildCode, myGuild);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        let guild = await GuildModel.findByCode(myGuild.guildCode, serverId, GUILD_SELECT.INVITED_MEMBER);
        let invitedMembers = guild.invitedMembers;
        if(shouldRefresh(guild.inviteTime, new Date())) {
            invitedMembers = [];
        }

        // 离线时间，三天内在线且尚未加入军团。按以下规则排序  离线时间 玩家等级 玩家战力
        
        const day = <number>getTimeFun().getBeforeDay(3);

        const { quitGuildTime: quitTime = 0 } = await RoleModel.findByRoleId(roleId);
        let allList = await RoleModel.getInviteList(day, serverId);
        allList = allList.filter(cur => !invitedMembers.includes(cur.roleId))
        let list = getRandEelm(allList, 10);
        if(!list.length) list = allList;
        list = sortArrRandom(list);

        let result = [];
        for(let cur of list) {
            let isOnline = await isRoleOnline(cur.roleId);
            result.push({...cur, isOnline})
        }

        return resResult(STATUS.SUCCESS, { quitTime, list: result });

    }

    // 团长（一键）邀请人
    async inviteMember(msg: { code: string, roleIds: string[] }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const { code, roleIds } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.INVATE_MEMBER, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await GuildModel.findByCode(code, serverId, GUILD_SELECT.INVITED_MEMBER);
        if(guild.isMemberMax) return resResult(STATUS.GUILD_MEMBER_MAX);

        const roleList = await RoleModel.findRoleByField('roleId', roleIds);
        let result = new Array<string>();
        let uids = [];
        for(let role of roleList) {
            if(!role.hasGuild) {
                await UserGuildApplyModel.createUserGuildApply(role, guild, GUILD_APPLY_TYPE.INVITE);
                result.push(role.roleId);
                let hisInfo = await getRoleOnlineInfo(role.roleId);
                if(hisInfo.isOnline) {
                    uids.push({ uid: role.roleId, sid: hisInfo.sid })
                }
            }
        }
        await GuildModel.recordInvitedMember(code, serverId, roleIds, shouldRefresh(guild.inviteTime, new Date()));
        this.channelService.pushMessageByUids('onGuildInvite', resResult(STATUS.SUCCESS, { code }), uids);

        return resResult(STATUS.SUCCESS, { roleIds: result });

    }

    // 成员收到邀请列表
    async getInvitationList(msg: { lastApplyCode: string }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const { lastApplyCode } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.GET_INVITATION_LIST, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const result = await UserGuildApplyModel.findInviteByRole(roleId, lastApplyCode);
        const list = result.map(cur => {
            let guild = <GuildType>cur.guild;
            let leader = <RoleType>guild.leader;
            delete cur.guild;
            return { applyCode: cur.applyCode, ...guild, leader: leader.roleName };
        });

        return resResult(STATUS.SUCCESS, { list });

    }


    // 成员同意/拒绝邀请
    async receiveInvitation(msg: { applyCode: string, isReceived: boolean }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const { applyCode, isReceived } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.RECEIVE_INVITAION, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const invite = await UserGuildApplyModel.findByCode(applyCode);
        if(!invite) return resResult(STATUS.GUILD_INVITE_NOT_FOUND);

        let code: string;
        if(isReceived) { // 同意申请，加入
            const { guildCode } = invite;
            const guild = await GuildModel.findByCode(guildCode, serverId);
    
            const joinResult = await joinGuild(guildCode, guild.name, guild.lv, roleId, serverId, session);
            if(joinResult.status == -1) {
                return joinResult.resResult;
            }

            let chatSid = await getGuildChannelSid(code);
            // 更新人数增加
            this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { memberCnt: joinResult.memberCnt, guildCe: joinResult.guildCe });
            // 添加动态
            const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.JOIN_GUILD, [joinResult.roleName]);
            this.app.rpc.chat.guildRemote.addRec.toServer(chatSid, rec);

            code = guild.code;
        }
        await UserGuildApplyModel.deleteByApplyCode([applyCode]); // 删除这条邀请

        return resResult(STATUS.SUCCESS, { applyCode, code, isReceived, hasGuild: isReceived });
    }

    // 获取军团成员
    async getGuildMember(msg: { code: string, sort: string }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        // const serverId = session.get('serverId');
        const { code, sort } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.GET_MEMBER_LIST_MAIN, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        let select = ['role', 'job'];
        const checkDetailResult = await checkAuth(GUILD_OPERATE.GET_MEMBER_LIST_DETAIL, roleId, code);
        if(checkDetailResult) {
            select.push('auth', 'activeWeekly activeUpdateTime');
        }
        let list = await UserGuildModel.getListByGuild(code, select.join(' '), { auth: 1 });
        let result = [];
        for(let cur of list) {
            let role = <RoleType>cur.role;
            delete role._id;
            delete cur.role;
            let isOnline = await isRoleOnline(role.roleId)
            result.push({ ...cur, ...role, isOnline: !!isOnline });
        }
        let leader = result.shift();

        result.sort((a, b) => {
            if(sort == 'active') {
                if(b.activeWeekly == a.activeWeekly) {
                    return a.activeUpdateTime - b.activeUpdateTime
                } else {
                    return b.activeWeekly - a.activeWeekly
                }
            } else if (sort == 'loginTime') {
                return b.quitTime - a.quitTime;
            } else {
                return b.ce - a.ce;
            }
        });

        result.unshift(leader);
        return resResult(STATUS.SUCCESS, { list: result });
    }

    // 团长解散军团
    async dismiss(msg: { code: string }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const { code } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.DISMISS, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await GuildModel.dismiss(code, serverId);
        if(!guild) return resResult(STATUS.GUILD_DELETE_ERROR);

        await UserGuildModel.dismiss(code);
        const { members } = guild;
        await RoleModel.dissmissGuild(members);
        await UserGuildApplyModel.deleteApplyByGuild(code);

        // 删除channel

        let chatSid = await getGuildChannelSid(code);
        this.app.rpc.chat.guildRemote.dismiss.toServer(chatSid,code);

        let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, {serverId});
        await r.removeFromRank({ guildCode: code });
        let r2 = new Rank(REDIS_KEY.GUILD_LV_RANK, {serverId});
        await r2.removeFromRank({ guildCode: code });

        return resResult(STATUS.SUCCESS, { code, status: guild.status });
    }

    // 成员退出军团
    async quit(msg: { code: string }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const sid = session.get('sid');
        const { code } = msg;

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.QUIT, roleId, code);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const userGuild = await UserGuildModel.quit(code, roleId);
        if(!userGuild) return resResult(STATUS.GUILD_QUIT_ERROR);

        const role = await RoleModel.quitGuild(roleId, nowSeconds());
        if(!role) return resResult(STATUS.GUILD_QUIT_ERROR);

        const guild = await GuildModel.quit(code, roleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER);
        if(!guild) return resResult(STATUS.GUILD_QUIT_ERROR);
        await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }])

        //删除排名信息
        await removeBossRank(code, roleId);
        await removeTrainRank(code, roleId, guild.trainId);
        // 添加动态
        const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.QUIT_GUILD, [roleName]);
        let chatSid = await getGuildChannelSid(code);
        this.app.rpc.chat.guildRemote.addRec.toServer(chatSid,rec);
        this.app.rpc.chat.guildRemote.memberQuit.toServer(chatSid,code, roleId, guild, sid);

        session.set('guildCode', '');
        session.push('guild', () => {});
        
        return resResult(STATUS.SUCCESS, { hasGuild: role.hasGuild });
    }

    // 团长踢退出军团
    async kick(msg: { code: string, roleId: string }, session: BackendSession) {
    
        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const { code, roleId: memberRoleId } = msg;

        // 检查权限
        const checkMyAuth = await checkAuth(GUILD_OPERATE.KICK, roleId, code);
        if(!checkMyAuth) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        // 被踢出的权限
        const checkHisAuth = await checkAuth(GUILD_OPERATE.BE_KICKED, memberRoleId, code);
        if(!checkHisAuth) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);


        const userGuild = await UserGuildModel.quit(code, memberRoleId);
        if(!userGuild) return resResult(STATUS.GUILD_KICK_ERROR);

        const role = await RoleModel.quitGuild(memberRoleId, nowSeconds());
        if(!role) return resResult(STATUS.GUILD_KICK_ERROR);

        const guild = await GuildModel.quit(code, memberRoleId, serverId, role.ce, userGuild.auth == GUILD_AUTH.MANAGER);
        if(!guild) return resResult(STATUS.GUILD_KICK_ERROR);
        await updateUserInfo(REDIS_KEY.GUILD_INFO, guild.code, [{ field: 'guildCe', value: guild.guildCe }])

        //删除排名信息
        await removeBossRank(code, roleId);
        await removeTrainRank(code, roleId, guild.trainId);
        let chatSid = await getGuildChannelSid(code);

        const { sid } = await getRoleOnlineInfo(roleId);
        this.app.rpc.chat.guildRemote.memberQuit.toServer(chatSid,code, roleId, guild, sid);

        // 添加动态
        const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.QUIT_GUILD, [role.roleName]);
        this.app.rpc.chat.guildRemote.addRec.toServer(chatSid,rec);
        await sendMailByContent(MAIL_TYPE.GUILD_BE_KICK, memberRoleId, { sendName: roleName, params: [guild.name] });

        return resResult(STATUS.SUCCESS, { memberCnt: guild.memberCnt });
    }

    // 团员弹劾团长
    async impeach(msg: { code: string, roleId: string }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const sid = session.get('sid');
        const serverId = session.get('serverId');
        const { code, roleId: leaderRoleId } = msg;

        // 弹劾的权限
        const checkMyAuth = await checkAuth(GUILD_OPERATE.IMPEACH, roleId, code);
        if (!checkMyAuth) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        // 被弹劾的权限
        const checkHisAuth = await checkAuth(GUILD_OPERATE.BE_IMPEACH, leaderRoleId, code);
        if (!checkHisAuth) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        // 离线72小时
        const { roleName: oldRoleName, quitTime } = await RoleModel.findByRoleId(leaderRoleId);
        if (quitTime > <number>getTimeFun().getBeforeDay(3)) {
            return resResult(STATUS.GUILD_LEADER_LOGIN);
        }
        // 上周周功勋最高的人
        const topUserGuilds = await UserGuildModel.findTopActive(code, 'auth role roleId');
        if (topUserGuilds.length <= 0) {
            return resResult(STATUS.GUILD_MEMBER_NOT_FOUND);
        }
        let topUserGuild: UserGuildType;
        for(let userGuild of topUserGuilds) {
            let role = await RoleModel.findByRoleId(userGuild.roleId, 'quitTime');
            if(role && role.quitTime > <number>getTimeFun().getBeforeDay(3)) {
                topUserGuild = userGuild; break;
            }
        }
        if (!topUserGuild) {
            return resResult(STATUS.GUILD_MEMBER_NOT_FOUND);
        }

        // 检查元宝是否够
        const role = await RoleModel.findByRoleId(roleId);
        if(ARMY.ARMY_IMPEACH_COST > role.gold) {
            return resResult(STATUS.DAILY_REFRESH_GOLD_LACK);
        }
        await handleCost(roleId, sid, [getGoldObject(ARMY.ARMY_IMPEACH_COST)]);

        const topUser = <RoleType>topUserGuild.role;
        // 交换

        await UserGuildModel.updateInfo(leaderRoleId, { auth: GUILD_AUTH.MEMBER, job: GUILD_JOB.SHIBING }, {}, 'auth'); // 团长撤
        await UserGuildModel.updateInfo(topUserGuild.roleId, { auth: GUILD_AUTH.LEADER, job: GUILD_JOB.JIANGJUN }, {}, 'auth'); // 最高功勋人升
        let managerCntInc = topUserGuild.auth == GUILD_AUTH.MANAGER ? -1 : 0; // 管理人数

        const guild = await GuildModel.updateInfo(code, { leader: topUser._id }, { managerCnt: managerCntInc }, 'managerCnt name'); // 如果有转让团长设置leader

        // 添加动态
        let chatSid = await getGuildChannelSid(code);
        const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.IMPEACH, [ oldRoleName, topUser.roleName]);
        this.app.rpc.chat.guildRemote.addRec.toServer(chatSid,rec);

        this.app.rpc.chat.guildRemote.changeLeader.toServer(chatSid,code, guild.managerCnt, topUser, leaderRoleId);
        await sendMailByContent(MAIL_TYPE.GUILD_BE_IMPEACH, leaderRoleId, { sendName: roleName, params: [guild.name] });
        await sendMailByContent(MAIL_TYPE.GUILD_BE_SET_LEADER, topUser.roleId, { sendName: roleName, params: [guild.name] });

        await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{field: 'leader', value: new GuildLeader(topUser) } ]);

        let isOnline = await isRoleOnline(topUser.roleId);
        const leader = { ...topUser, ce: topUser.ce, isOnline }
        return resResult(STATUS.SUCCESS, {
            code, managerCnt: guild.managerCnt, leader
        });
    }

    // 升级建筑物等级
    async upStructure(msg: { code: string, id: number }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const sid = session.get('sid');
        const { code, id } = msg;

        // 升级建筑物权限
        const checkResult = await checkAuth(GUILD_OPERATE.UP_STRUCTURE, roleId, code);
        if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await GuildModel.findByCode(code, serverId, 'lv structure');
        if(!guild) {
            return resResult(STATUS.GUILD_NOT_FOUND);
        }

        const { lv, structure } = guild;
        const curStructure = structure.find(cur => cur.id == id);
        if(!curStructure) {
            return resResult(STATUS.GUILD_STRUCTURE_NOT_FOUND);
        }
        if(id != GUILD_STRUCTURE.ARMY_CENTER && curStructure.lv >= lv) { // 中军大帐以外建筑物
            if(curStructure.lv >= lv) {
                return resResult(STATUS.GUILD_STRUCTURE_LV_MAX);
            }
        }
        if(!hasStructureConsume(id, curStructure.lv + 1)) {
            return resResult(STATUS.GUILD_STRUCTURE_LV_MAX);
        }
        const cost = getStructureConsume(id, curStructure.lv);
        
        const result = await GuildModel.upStructure(code, id, cost, 'code fund structure lv name');
        if(!result) {
            return resResult(STATUS.GUILD_FUND_NOT_ENOUGH);
        }
        if(id == GUILD_STRUCTURE.ARMY_CENTER) {
            let r = new Rank(REDIS_KEY.GUILD_LV_RANK, { serverId });
            await r.setRankWithGuildInfo(code, guild.lv, guild.lvUpdateTime, guild);        
        }
        
        const resultStructure = result.structure.find(cur => cur.id == id);

        // 修改信息
        let chatSid = await getGuildChannelSid(code);
        this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid,code, { ...result });
        await updateUserInfo(REDIS_KEY.GUILD_INFO, code, [{field: 'lv', value: result.lv } ]);

        // 添加动态
        const structureName = GUILD_STRUCTURE_NAME.get(id);
        const rec = await GuildRecModel.createGuildRec(roleId, code, GUILD_REC_TYPE.STRUCTURE_UP, [structureName, resultStructure.lv.toString()]);
        this.app.rpc.chat.guildRemote.addRec.toServer(chatSid,rec);

        // 军团频道聊天消息
        pushGuildUpStructureMsg(roleId, roleName, result, resultStructure);

        return resResult(STATUS.SUCCESS, result);
    }


    // 获取动态
    async getRec(msg: { code: string }, session: BackendSession) {

        const roleId = session.get('roleId');
        const { code } = msg;

        const checkResult = await checkAuth(GUILD_OPERATE.GET_REC, roleId, code);
        if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        // console.log(startTime)
        const list = await GuildRecModel.getGuildRec(code, <number>getTimeFun().getBeforeDayWithHour(3));

        return resResult(STATUS.SUCCESS, { list });
    }

    // 团长发送消息给军团内所有成员的邮箱
    async sendMail(msg: { code: string, info: string }, session: BackendSession) {

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

        const checkResult = await checkAuth(GUILD_OPERATE.SEND_MAIL, roleId, code);
        if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await GuildModel.findByCode(code, serverId, 'members');
        if(!guild) return resResult(STATUS.GUILD_NOT_FOUND);

        const { members } = guild;
        //下发邮件
        let f = new SendMailFun();
        f.setWithContentId(MAIL_TYPE.SEND_MAIL, { sendName: roleName, params: [info] });
        await f.sendToGuild(code, members);

        return resResult(STATUS.SUCCESS, { isSuccess: true });
    }

    // 团长发送世界频道
    async recruit(msg: { code: string, info: string }, session: BackendSession) {

        const roleId = session.get('roleId');
        // const roleName = session.get('roleName');
        const sid = session.get('sid');
        const serverId = session.get('serverId');
        const { code, info } = msg;

        const checkResult = await checkAuth(GUILD_OPERATE.RECRUIT, roleId, code);
        if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await GuildModel.findByCode(code, serverId);
        if(!guild) return resResult(STATUS.GUILD_NOT_FOUND);

        // 发送世界频道消息
        this.app.rpc.chat.chatRemote.sendWorldMessage.toServer('chat-server-1', serverId, { info });

        return resResult(STATUS.SUCCESS, { isSuccess: true });
    }

    // 领取活跃奖励
    async receiveActiveBox(msg: { code: string, id: number }, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const sid = session.get('sid');
        const serverId = session.get('serverId');
        const funcs: number[] = session.get('funcs');
        const { code, id } = msg;

        let userGuild = await getUserGuildWithRefActive(roleId, 'receivedActive auth guildCode');
        if(!userGuild) return resResult(STATUS.GUILD_NOT_FOUND);

        const checkResult = await checkAuth(GUILD_OPERATE.RECEIVE_ACTIVE, roleId, code, userGuild);
        if (!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);

        const guild = await getGuildWithRefActive(code, serverId);
        if(!guild) return resResult(STATUS.GUILD_NOT_FOUND);

        let activeDayReward = gameData.guildActiveDayReward.get(id);
        if(!activeDayReward) return resResult(STATUS.GUILD_ACTIVE_BOX_NOT_FOUND);

        if(guild.activeDaily < activeDayReward.activeDayPoint) {
            return resResult(STATUS.GUILD_ACTIVE_POINT_NOT_REACH);
        }

        if(userGuild.receivedActive.includes(id)) {
            return resResult(STATUS.GUILD_ACTIVE_BOX_HAS_RECEIVED);
        }
        userGuild.receivedActive.push(id);

        let goods = await addItems(roleId, roleName, sid, activeDayReward.reward);
        userGuild = await UserGuildModel.updateInfo(roleId, { receivedActive: userGuild.receivedActive }, {}, 'receivedActive');

        // 任务
        await checkTask(roleId, sid, funcs, TASK_TYPE.GUILD_RECEIVE_BOX, 1, true, {});

        return resResult(STATUS.SUCCESS, { goods, receivedActive: userGuild.receivedActive });
    }

    // 查看活跃排行榜
    async getActiveRank(msg: { }, session: BackendSession) {

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

        const myUserGuild = await UserGuildModel.getMyGuild(roleId, 'auth guildCode');
        if(!myUserGuild) return resResult(STATUS.GUILD_NOT_FOUND);

        // 检查权限
        const checkResult = await checkAuth(GUILD_OPERATE.GET_ACTIVE_RANK, roleId);
        if(!checkResult) return resResult(STATUS.GUILD_AUTH_NOT_ENOUGH);
                
        let r = new Rank(REDIS_KEY.GUILD_ACTIVE_RANK, { serverId });
        let { ranks, myRank } = await r.getRankListWithMyRank({ guildCode: myUserGuild.guildCode });
        if(!myRank) {
            let guild = await GuildModel.findByCode(myUserGuild.guildCode, serverId, 'code icon name lv leader activeWeekly');
            myRank = await r.generMyRankWithGuild(myUserGuild.guildCode, guild.activeWeekly, guild.activeUpdateTime, guild);
        }

        return resResult(STATUS.SUCCESS, { ranks, myRank });
    }

    // debug接口： 添加公会活跃值
    async debugAddActive(msg: { code: string, active: number, id: number }, session: BackendSession) {

        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const { code, active, id } = msg;

        const result = await addActive(roleId, serverId, id, null, active);
        if(result.status == 0) return result.resResult;
        const { guild, userGuild } = result;

        let { activeDaily, activeWeekly } = guild;
        let chatSid = await getGuildChannelSid(code);

        this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, { activeDaily, activeWeekly });

        return resResult(STATUS.SUCCESS, { activeDaily, activeWeekly, myInfo: userGuild });
    }

    // debug接口： 调用定时任务
    async debugWeeklyRask(msg: { }, session: BackendSession) {

        await settleGuildWeekly();
        return resResult(STATUS.SUCCESS);
    }

    // debug接口： 添加军团资金
    async debugAdddFund(msg: { code: string, count: number }, session: BackendSession) {

        const { code, count } = msg;
        const guild = await GuildModel.updateInfo(code, {}, { fund: count }, 'fund');
        let chatSid = await getGuildChannelSid(code);
        this.app.rpc.chat.guildRemote.updateInfo.toServer(chatSid, code, {fund: guild.fund});
        return resResult(STATUS.SUCCESS, { code, fund: guild.fund });
    }

    // debug接口： 加长会长离线时间
    async debugLeaderLeaveTime(msg: { code: string }, session: BackendSession) {

        const { code } = msg;
        const serverId = session.get('serverId');
        const guild = await GuildModel.findByCode(code, serverId);
        const leader = <RoleType>guild.leader;
        let threeDaysBefore = <number>getTimeFun().getBeforeDay(3);
        await RoleModel.updateRoleInfo(leader.roleId, { quitTime: threeDaysBefore } );

        return resResult(STATUS.SUCCESS, { code });
    }
}