import { Service } from 'egg';
import { STATUS, MARQUEE_TYPE } from '@consts';
import { GameModel } from '@db/Game';
import { ServerlistModel, ServerlistUpdate } from '@db/Serverlist';
import { gameData } from '@pubUtils/data';
import { DicHero } from '@pubUtils/dictionary/DicHero';
import { DicRMB } from '@pubUtils/dictionary/DicRMB';
import { DicActivityType } from '@pubUtils/dictionary/DicActivityType';
import { DicTaskType } from '@pubUtils/dictionary/DicTaskType';
import { ServerStategyModel, ServerStategyTypeParam } from '@db/ServerStategy';
import { NoticeModel, NoticeTypeParam, NoticeType } from '@db/Notice';
import { MarqueeModel, MarqueeParam, MarqueeType } from '@db/Marquee';
import { MaintenanceModel, MaintenanceTypeParam } from '@db/Maintenance';
import { GMMailTypeParam, GMMailModel, GMMailType } from '@db/GMMail';
import { AccuseRecModel } from '@db/AccuseRec';

/**
 * Test Service
 */
export default class Game extends Service {

    /**
     * 获取正式服，测试服，开发服等环境
     */
    public async getServerEnv() {
        const { ctx, app } = this;
        const list = await GameModel.getServerEnvList();

        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list,
            env: app.config.env
        });
    }

    /**
     * 获取正式服，测试服，开发服等环境
     */
    public async getServerListByEnv() {
        const { ctx, app } = this;
        let env = app.config.env
        let serverEnv = await GameModel.getServerEnvList();
        let curEnv = serverEnv.find(cur => cur.env == env);
        const list = await ServerlistModel.findByServerType(curEnv?.serverType);

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

    public async getServerList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { id?: number, serverId?: string|number, name?: string, groupName?: string, groupId?: number, serverType?: string } = {}) {
        const { ctx } = this;

        const list = await ServerlistModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await ServerlistModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list, total
        });
    }

    public async getMaintenanceList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { isOpen?: boolean } = {}) {
        const { ctx } = this;

        const list = await MaintenanceModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await MaintenanceModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                let marquee = <MarqueeType>cur.marquee;
                let notice = <NoticeType>cur.notice;
                return {
                    ...cur, startTime: cur.startTime.getTime(),
                    marquee: marquee?{...marquee, startTime: marquee.startTime.getTime(), endTime: marquee.endTime.getTime()}:null,
                    notice: notice?{...notice, startTime: notice.startTime.getTime(), endTime: notice.endTime.getTime(), showStartTime: notice.showStartTime.getTime(), showEndTime: notice.showEndTime.getTime()}:null
                }
            }), total
        });
    }

    public async updateMaintenance(values: MaintenanceTypeParam, marquee: MarqueeParam, notice: NoticeTypeParam, mail: GMMailTypeParam) {
        const { ctx } = this;
        if(values.code == 'new') {
            let serverEnv = await GameModel.getServerEnvList();
            let curEnv = serverEnv.find(cur => cur.env == this.app.config.env);
    
            let marqueeResult = await MarqueeModel.createData({ ...marquee, serverIds: values.serverIds, type: MARQUEE_TYPE.SCHEDULE, isRunning: false }, ctx.user?.uid);
            let noticeResult = await NoticeModel.updateNotice('new', { ...notice, type: 1, sort: 1000, serverType: curEnv?.serverType, isEnable: false }, ctx.user?.uid);
            let mailResult = await GMMailModel.addMail({ ...mail, useTempTime: true }, ctx.user?.uid);
            await MaintenanceModel.createData(values, marqueeResult, noticeResult, mailResult);
        } else {
            let maintenanceResult = await MaintenanceModel.updateData(values.code, values, ctx.user?.uid);
            if(!maintenanceResult) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
            let marqueeResult = <MarqueeType>maintenanceResult.marquee;
            let noticeResult = <NoticeType>maintenanceResult.notice;
            let mailResult = <GMMailType>maintenanceResult.mail;
            if(marqueeResult) await MarqueeModel.updateData(marqueeResult.code, marquee, ctx.user?.uid);
            if(noticeResult) await NoticeModel.updateNotice(noticeResult.id, notice, ctx.user?.uid);
            if(mailResult) await GMMailModel.updateMailById(mailResult._id, mail, ctx.user?.uid);
        }
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async getServerStategyList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { id?: number, name?: string }) {
        const { ctx } = this;

        const list = await ServerStategyModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await ServerStategyModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list, total
        });
    }

    public async updateServerStategy(values: ServerStategyTypeParam & {id: string|number}) {
        const { ctx } = this;

        try {
            await ServerStategyModel.updateServerStategy(values, ctx.user?.uid);
    
        } catch(e) {
            return ctx.service.utils.resResult(STATUS.INTERNAL_ERR, null, e.stack);
        }
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async createNewServer(name: string, openTime: number, serverType: string, stategyId: number ) {
        const { ctx } = this;

        try {
            let stategy = await ServerStategyModel.findBySId(stategyId);
            if(!stategy) return ctx.service.utils.resResult(STATUS.GM_STATEGY_NOT_FOUND);

            await ServerlistModel.newServer({ name, openTime: new Date(openTime), serverType }, stategy, ctx.user?.uid);
    
        } catch(e) {
            return ctx.service.utils.resResult(STATUS.INTERNAL_ERR, null, e.stack);
        }
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async updateServer(id: number, name: string, groupName: string, serverStatus: number ) {
        const { ctx } = this;

        try {
            let server = await ServerlistModel.findByServerId(id);
            if(!server) return ctx.service.utils.resResult(STATUS.GM_SERVER_NOT_FOUND);

            if(server.groupName != groupName) {
                await ServerlistModel.updateGroupName(server.groupId, groupName);
            }
            let update: ServerlistUpdate = {};
            if(name) update['name'] = name;
            if(groupName) update['groupName'] = groupName;
            if(serverStatus) update['serverStatus'] = serverStatus;

            await ServerlistModel.updateByServerId(id, update);
    
        } catch(e) {
            return ctx.service.utils.resResult(STATUS.INTERNAL_ERR, null, e.stack);
        }
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async getDicHero() {
        let list: DicHero[] = [];
        for(let [heroId, hero] of gameData.hero) {
            if(heroId <= 300) {
                list.push(hero)
            }
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicGoods() {
        let list = [];
        for(let [_, { good_id, name, pieceId, quality, itid, image_id }] of gameData.goods) {
            list.push({
                good_id, name, pieceId, quality, itid, image_id
            })
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicRmb() {
        let list: DicRMB[] = [];
        for(let [_, dicRmb] of gameData.rmb) {
            list.push(dicRmb);
        }
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicActivityType() {
        let list: DicActivityType[] = gameData.activityType;
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getDicTaskType() {
        let list: DicTaskType[] = gameData.taskTypeDesc;
        return this.ctx.service.utils.resResult(STATUS.SUCCESS, {
            list
        })
    }

    public async getNoticeList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { type?: number, content?: string }) {
        const { ctx } = this;
        const list = await NoticeModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await NoticeModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                return { ...cur, startTime: cur.startTime.getTime(), endTime: cur.endTime.getTime(), showEndTime: cur.showEndTime.getTime(), showStartTime: cur.showStartTime.getTime()}
            }), total
        });
    }

    public async updateNotice(id: string|number, params: NoticeTypeParam) {
        const { ctx } = this;
        if(params.startTime) params.startTime = new Date(params.startTime);
        if(params.endTime) params.endTime = new Date(params.endTime);
        if(params.showStartTime) params.showStartTime = new Date(params.showStartTime);
        if(params.showEndTime) params.showEndTime = new Date(params.showEndTime);
        let result = await NoticeModel.updateNotice(id, params);
        if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async delNotice(id: number) {
        const { ctx } = this;
        let result = await NoticeModel.delNotice(id);
        if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }


    public async getMarqueeList(page: number, pageSize: number, sortField: string, sortOrder: string, form: { type?: number, current?: boolean, content?: string }) {
        const { ctx } = this;
        const list = await MarqueeModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await MarqueeModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list: list.map(cur => {
                return { ...cur, startTime: cur.startTime?.getTime()||0, endTime: cur.endTime?.getTime()||0 }
            }), total
        });
    }

    public async updateMarquee(code: string, params: MarqueeParam) {
        const { ctx } = this;
        if(params.startTime) params.startTime = new Date(params.startTime);
        if(params.endTime) params.endTime = new Date(params.endTime);
        let result;
        if(code == 'new') {
            result = await MarqueeModel.createData(params);
        } else {
            result = await MarqueeModel.updateData(code, params);
        }
        if(!result) return ctx.service.utils.resResult(STATUS.WRONG_PARMS);
        return ctx.service.utils.resResult(STATUS.SUCCESS);
    }

    public async getAccuse(page: number, pageSize: number, sortField: string, sortOrder: string, form: {}) {
        const { ctx } = this;
        const list = await AccuseRecModel.findByCondition(page, pageSize, sortField, sortOrder, form);
        const total = await AccuseRecModel.countByCondition( form )
        return ctx.service.utils.resResult(STATUS.SUCCESS, {
            list, total
        });
    }
}
