/**
 * 全服邮件
 */
import MailTemp from './MailTemp';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { nowSeconds } from '../pubUtils/timeUtil';
import { MAIL_STATUS } from '../consts/constModules/mailConst';

class RoleStatus {
    @prop({ required: true })
    roleId: string;
    @prop({ required: true })
    status: number;
}

@index({ sendTime: 1 })
export default class ServerMail extends MailTemp {
    @prop({ required: true })
    serverId: number;			

    @prop({ required: true, type: RoleStatus })
    roleStatus: RoleStatus[]; 

    @prop({ required: true, type: String })
    delRoles: string[]; 
    
    /**
     * @description 根据玩家id获得所有有效邮件
     * @param {String} roleId 玩家id
     * @param {Number} serverId 服务器id
     */
    public static async findByRoleId(roleId: string, serverId: number) {
        const result: ServerMailType[] = await ServerMailModel.find({ 
            serverId,
            delRoles: { $ne: roleId },
            sendTime: { $lte: nowSeconds() } ,
            endTime: { $gte: nowSeconds() } 
        }).populate('mail').lean();
        return result;
    }

    public static async getMailById(_id: string, lean = true) {
        const result: ServerMailType = await ServerMailModel.findOne({ _id }).lean(lean);
        return result;
    }

    public static async findByTimeGap(beforeTime: number, time: number) {
        const result: ServerMailType[] = await ServerMailModel.find({ sendTime: { $gt: beforeTime, $lte: time } }).lean();
        return result;
    }

    public static async findBySendTime(time: number) {
        const result: ServerMailType[] = await ServerMailModel.find({ sendTime: time }).lean();
        return result;
    }

    /**
     * @description 创建邮件
     * @param params 
     */
    public static async addMail(params: ServerMailTypeParam) {
        const doc = new ServerMailModel();
        const mail = Object.assign(doc.toJSON(), params);
        delete mail._id;
        let rec: ServerMailType = await ServerMailModel.findByIdAndUpdate(doc._id, mail, { new: true, upsert: true }).lean();
        return rec;
    }
    /**
     * 根据id删除单条邮件
     * @param _id 
     * @param lean 
     */
    public static async delMailById(id: string, roleId: string) {
        const result: ServerMailType = await ServerMailModel.findOneAndUpdate(
            {
                _id: id,
                sendTime:{ $lte: nowSeconds() },
                'roleStatus.roleId': roleId,
                $or: [{
                    'roleStatus.status': MAIL_STATUS.READ, hasGoods:false
                }, {
                    'roleStatus.status': MAIL_STATUS.RECEIVED
                }]
            },
            { $set:{ 'roleStatus.$.status': MAIL_STATUS.DELETE}, $push: { delRoles: roleId } }, 
            { new: true }
            ).lean();

            // console.log('*******', result)
        return result;
    }

    /**
     * 根据玩家id批量删除
     * @param _id 
     * @param roleId 
     */
    public static async delMailsByRoleId(roleId: string) {
        const ids: { _id: string }[] = await ServerMailModel.find(
            { 
                sendTime:{ $lte: nowSeconds() },
                $or: [{
                    roleStatus: {$elemMatch: {roleId, status: MAIL_STATUS.READ}}, hasGoods:false
                }, {
                    roleStatus: {$elemMatch: {roleId, status: MAIL_STATUS.RECEIVED}}
                }]
            }
        ).select('_id').lean();
        let result: ServerMailType[] = [];
        for(let _id of ids) {
            let rec = await ServerMailModel.findOneAndUpdate({ _id, 'roleStatus.roleId': roleId }, { $set:{ 'roleStatus.$.status': MAIL_STATUS.DELETE }, $push: { delRoles: roleId }}, { new: true }).lean();
            result.push(rec);
        }
        return result;
    }


    public static async updateStatusWithCondition(_id: string, roleId: string, status: number, servermail?: ServerMailType) {
        if(!servermail) servermail = await ServerMailModel.findById(_id).lean();
        let { roleStatus } = servermail;
        let hasRole = roleStatus.find(cur => cur.roleId == roleId);
        if(hasRole) {
            servermail = await ServerMailModel.findOneAndUpdate({ _id, 'roleStatus.roleId': roleId }, { $set: { 'roleStatus.$.status': status } }, {new: true}).lean();
        } else {
            servermail = await ServerMailModel.findByIdAndUpdate(_id, { $push: { roleStatus: { roleId, status } } }, {new: true}).lean();
        }
        return servermail
    }

    /**
     * 查询有奖励的邮件
     * @param roleId 
     * @param lean 
     */
    public static async findRewardsMails(serverId: number, roleId: string, lean = true) {
        const allMails: ServerMailType[] = await ServerMailModel.find({ serverId, sendTime:{$lte: nowSeconds()} }).lean(lean);
        let result: ServerMailType[] = [];
        for(let mail of allMails) {
            let { roleStatus } = mail;
            let hasRole = roleStatus.find(cur => cur.roleId == roleId);
            if(hasRole) {
                if(hasRole.status == MAIL_STATUS.CREATE || hasRole.status == MAIL_STATUS.READ) {
                    result.push(mail);
                }
            } else {
                result.push(mail);
            }
        }
        return result;
    }
}

export const ServerMailModel = getModelForClass(ServerMail);

export interface ServerMailType extends Pick<DocumentType<ServerMail>, keyof ServerMail>{}
export type ServerMailTypeParam = Partial<ServerMailType>; // 将所有字段变成可选项
