import { CHANNEL_PREFIX, MSG_SOURCE, getChannelType } from './../../../consts/constModules/chatConst';
import { Application, BackendSession, HandlerService, } from 'pinus';
import { resResult } from '../../../pubUtils/util';
import { DEFAULT_MSG_PER_PAGE, STATUS, TASK_TYPE } from '../../../consts';
import { createAccuseData, createGroupMsg, createPrivateMsg, getPrivateMessages, pushGroupMsgToRoom, pushMsgToRole, updatePrivateMsgReadInfo, recentPrivateChatInfos, recentWorldMsgs, recentSysMsgs, recentGuildMsgs, updatePrivateMsgIsTop, delPrivateMsg, recentServerGroupMsgs, recentLeagueMsgs } from '../../../services/chatService';
import { getSimpleRoleInfo } from '../../../services/roleService';
import { checkTask } from '../../../services/task/taskService';
import { RoleModel } from '../../../db/Role';
import { getFriendRelationType } from '../../../services/friendService';
import { GVGLeagueModel } from '../../../db/GVGLeague';
import { getGroupIdOfServer } from '../../../services/gvg/gvgService';
import { getGuildCodeString } from '../../../services/gvg/gvgRecService';


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

export class ChatHandler {
    constructor(private app: Application) {
    }

    /**
     * @description 群聊发送接口
     * @param {{ channel: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }} msg
     * @param {BackendSession} session
     * @memberof ChatHandler
     */
    async sendGroupMessage(msg: { channel: string, type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) {
        const { channel, type, content, targetRoleId, targetMsgCode } = msg;
        if (channel === CHANNEL_PREFIX.SYS) return resResult(STATUS.SYS_CHANNEL_AUTH_NOT_ENOUGH);
        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const serverId = session.get('serverId');
        const guildCode = session.get('guildCode');
        
        const sid = session.get('sid');
        let channelId = '', otherInfo = '';
        if (channel === CHANNEL_PREFIX.WORLD) channelId = `${serverId}`;
        if (channel === CHANNEL_PREFIX.GUILD) channelId = guildCode;
        if (channel === CHANNEL_PREFIX.GVG) {
            let groupId = await getGroupIdOfServer(serverId);
            channelId = `${groupId}`;
        }
        if (channel == CHANNEL_PREFIX.LEAGUE) {
            let myLeague = await GVGLeagueModel.findLeagueByGuild(guildCode);
            if(!myLeague) return resResult(STATUS.GVG_NOT_JOIN_LEAGUE);
            channelId = myLeague.leagueCode;
            otherInfo = getGuildCodeString(myLeague);
        }
        const msgData = await createGroupMsg(roleId, roleName, channel, channelId, type, MSG_SOURCE.ROLE_SEND_TEXT, content, targetRoleId, targetMsgCode, otherInfo);
        if (!msgData) return resResult(STATUS.WRONG_PARMS);
        await pushGroupMsgToRoom(msgData);

        // 任务
        await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType(channel) });

        return resResult(STATUS.SUCCESS, msgData);
    }

    /**
     * @description 私聊发送接口
     * @param {{ type: number, content: string, targetRoleId: string, targetMsgCode: string }} msg
     * @param {BackendSession} session
     * @memberof ChatHandler
     */
    async sendPrivateMessage(msg: { type: number, content: string, targetRoleId: string, targetMsgCode: string }, session: BackendSession) {
        const { type, content, targetRoleId, targetMsgCode } = msg;
        const roleId = session.get('roleId');
        const serverId = session.get('serverId');
        const roleName = session.get('roleName');
        
        const sid = session.get('sid');
        let relation = await getFriendRelationType(roleId, targetRoleId);
        const msgData = await createPrivateMsg(roleId, roleName, type, MSG_SOURCE.ROLE_SEND_TEXT, content, targetRoleId, targetMsgCode, relation);
        await pushMsgToRole(msgData);
        if (!msgData) return resResult(STATUS.WRONG_PARMS);

        // 任务
        await checkTask(serverId, roleId, sid, TASK_TYPE.CHAT, { chatType: getChannelType('private') });
        return resResult(STATUS.SUCCESS, msgData);
    }

    /**
     * @description 获取初始聊天消息，数据和登录时返回的一致
     * @param {{}} msg
     * @memberof ChatHandler
     */
    async getInitMessage(msg: {}, session: BackendSession) {

    }

    /**
     * @description 获取最近私聊对象列表
     * @param {{}} msg 
     * @param session 
     */
    async getRecentPrivateChats(msg: {}, session: BackendSession) {

        const roleId = session.get('roleId');
        const roleName = session.get('roleName');

        const recentPrivateChats = await recentPrivateChatInfos(roleId, roleName) || [];

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

    /**
     * @description 获取群组聊天记录
     * @param {{}} msg 
     * @param session 
     */
    async getGroupMessages(msg: {}, session: BackendSession) {
        const serverId: number = session.get('serverId');
        const guildCode: string = session.get('guildCode');

        const worldMsgs = await recentWorldMsgs(serverId);
        const sysMsgs = await recentSysMsgs(serverId);
        const guildMsgs = await recentGuildMsgs(guildCode);
        const gvgMsgs = await recentServerGroupMsgs(serverId);
        const leagueMsgs = await recentLeagueMsgs(guildCode);

        return resResult(STATUS.SUCCESS, { worldMsgs, sysMsgs, guildMsgs, gvgMsgs, leagueMsgs })
    }

    /**
     * @description 获取私聊历史消息
     * @param {{targetRoleId: string, fromSeqId: number, count: number}} msg 聊天对象；聊天消息的顺序 id，不传为从最新开始；count 为消息条数
     * @memberof ChatHandler
     */
    async getPrivateMessage(msg: { targetRoleId: string, fromSeqId: number, count: number }, session: BackendSession) {
        const roleId = session.get('roleId');
        const { targetRoleId, fromSeqId = Infinity, count = DEFAULT_MSG_PER_PAGE } = msg;
        const msgs = await getPrivateMessages(roleId, targetRoleId, fromSeqId, count);
        const targetRoleInfo = await getSimpleRoleInfo(targetRoleId);
        return resResult(STATUS.SUCCESS, { targetRoleId, msgs, targetRoleInfo });
    }

    /**
     * @description 查看私聊，主要用于更新最后查看时间和未读消息数
     * @param {{ targetRoleId: string }} msg
     * @param {BackendSession} session
     * @returns
     * @memberof ChatHandler
     */
    async readPrivateMessage(msg: { targetRoleId: string }, session: BackendSession) {
        const roleId = session.get('roleId');
        const { targetRoleId } = msg;
        const result = await updatePrivateMsgReadInfo(roleId, targetRoleId);
        if (!result) {
            return resResult(STATUS.UPDATE_PRIVATE_MSG_READ_TIME_ERR);
        }
        return resResult(STATUS.SUCCESS, result);
    }

    /**
     * @description 设置置顶
     * @param {{ targetRoleId: string, isTop: boolean }} msg
     * @param {BackendSession} session
     * @returns
     * @memberof ChatHandler
     */
    async setPrivateMessageTop(msg: { targetRoleId: string, isTop: boolean }, session: BackendSession) {
        const roleId = session.get('roleId');
        const { targetRoleId, isTop } = msg;
        const result = await updatePrivateMsgIsTop(roleId, targetRoleId, isTop);
        if (!result) {
            return resResult(STATUS.SET_PRIVATE_MSG_TOP_ERR);
        }
        return resResult(STATUS.SUCCESS, result);
    }

    /**
     * @description 删除私聊
     * @param {{ targetRoleId: string }} msg
     * @param {BackendSession} session
     * @returns
     * @memberof ChatHandler
     */
    async delPrivateMessage(msg: { targetRoleId: string }, session: BackendSession) {
        const roleId = session.get('roleId');
        const { targetRoleId } = msg;
        const result = await delPrivateMsg(roleId, targetRoleId);
        if (!result) {
            return resResult(STATUS.DEL_PRIVATE_MSG_ERR);
        }
        return resResult(STATUS.SUCCESS, result);
    }

    /**
     * @description 举报玩家的消息
     * @param {{targetRoleId: string, targetMsgCode: string; reason: number}} msg 被举报玩家的 Id，被举报的消息编号，举报原因
     * @param {BackendSession} session
     * @returns
     * @memberof ChatHandler
     */
    async accuse(msg: { targetRoleId: string, targetMsgCode: string; reason: number }, session: BackendSession) {
        const roleId = session.get('roleId');
        const roleName = session.get('roleName');
        const { targetRoleId, targetMsgCode, reason } = msg;
        let targetRole = await RoleModel.findByRoleId(targetRoleId);
        if(!targetRoleId) return resResult(STATUS.ROLE_NOT_FOUND);
        const accuseRec = await createAccuseData(roleId, roleName, targetRoleId, targetRole.roleName, targetMsgCode, reason);
        if (!accuseRec) return resResult(STATUS.WRONG_PARMS);
        return resResult(STATUS.SUCCESS, accuseRec);
    }
}
