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

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

@index({ 'roleStatus.roleId': 1 })
export default class GroupMail extends MailTemp {

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

    @prop({ required: false })
    leagueCode: string;
    /**
     * @description 根据玩家id获得所有有效邮件
     * @param {String} roleId 玩家id
     */
    public static async findByRoleId(roleId: string) {
        const result: GroupMailType[] = await GroupMailModel.find({ 
            $and: [
                {'roleStatus.roleId': roleId}, 
                {'roleStatus.status': { $in: [ MAIL_STATUS.CREATE, MAIL_STATUS.READ, MAIL_STATUS.RECEIVED ] }}
            ], 
            sendTime: { $lte: nowSeconds() } , 
            endTime: { $gte: nowSeconds() } 
        }).populate('mail').lean();
        return result;
    }

    /**
     * @description 创建邮件
     * @param params 
     */
    public static async addMail(params: GroupMailTypeParam) {
        const doc = new GroupMailModel();
        const mail = Object.assign(doc.toJSON(), params);
        delete mail._id;
        let rec: GroupMailType = await GroupMailModel.findByIdAndUpdate(doc._id, mail, { new: true, upsert: true }).populate('mail').lean();
        return rec;
    }

    /**
     * 根据id删除单条邮件
     * @param _id 
     */
    public static async delMailById(_id: string, roleId: string) {
        const result: GroupMailType = await GroupMailModel.findOneAndUpdate(
            { 
                _id, sendTime:{ $lte: nowSeconds() },
                $and: [{
                    'roleStatus.roleId': roleId,
                },{
                    $or: [{
                        'roleStatus.status': MAIL_STATUS.READ, hasGoods:false
                    }, {
                        'roleStatus.status': MAIL_STATUS.RECEIVED
                    }]
                }],
            },
            { $set:{ 'roleStatus.$.status': MAIL_STATUS.DELETE } }, 
            { new: true }
            ).lean();
        return result;
    }

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

    public static async getGroupMailsByRoleId(roleId: string, lean = true) {
        const result: GroupMailType[] = await GroupMailModel.find({ $and:[{'roleStatus.roleId': roleId}, { 'roleStatus.status': { $ne: -1}}], sendTime:{$lte: nowSeconds()} }).lean(lean);
        return result;
    }

    public static async getMail( mailId: string, mailTemType: number, lean = true) {
        const result: GroupMailType = await GroupMailModel.findOne({ mailId, mailTemType, sendTime:{$lte: nowSeconds()} }).lean(lean);
        return result;
    }

    public static async pushRoleMail( roleId: string, mailId: string, mailTemType: number, lean = true) {
        const result: GroupMailType = await GroupMailModel.findOneAndUpdate({ mailId, mailTemType, sendTime:{$lte: nowSeconds()} }, {$push: {roleStatus: {roleId, status: 0}}}).lean(lean);
        return result;
    }

    public static async getMailById(_id: string, lean = true) {
        const result: GroupMailType = await GroupMailModel.findOne({ _id, sendTime:{$lte: nowSeconds()} }).lean(lean);
        return result;
    }

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

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

    public static async updateStatusWithCondition(_id: string, roleId: string, status: number) {
        const result: GroupMailType = await GroupMailModel.findOneAndUpdate({ _id, 'roleStatus.roleId': roleId, sendTime:{$lte: nowSeconds()} }, {$set:{ 'roleStatus.$.status': status }}, { new: true }).lean();
        return result;
    }

    public static async deleteMail(_id: string, roleId: string, status: number, lean = true) {
        const result: GroupMailType = await GroupMailModel.findOneAndUpdate({ _id, 'roleStatus.roleId': roleId, sendTime:{$lte: nowSeconds()}}, {$set:{ 'roleStatus.$.status': status }}, { new: true }).lean(lean);
        return result;
    }

    public static async findReadAndRewardsMails(roleId: string, lean = true) {
        const ids: GroupMailType[] = await GroupMailModel.find({ sendTime:{$lte: nowSeconds()}, roleStatus: { $elemMatch: { roleId,  $or:[ {$and: [{status: MAIL_STATUS.READ}, { hasGoods: false }]},{status: MAIL_STATUS.RECEIVED} ] } } }).select('_id').lean(lean);
        return ids;
    }

    public static async updateStatusByIds(ids: string[], status: number, roleId: string, lean = true) {
        let mails = [];
        for(let id of ids) {
            const result: GroupMailType = await GroupMailModel.findOneAndUpdate({_id: id, "roleStatus.roleId": roleId}, { $set:{ 'roleStatus.$.status': status } }, { new: true }).lean(lean);
            let { status: resStatus } = findWhere(result.roleStatus, { roleId });
            mails.push({id: result._id, status: resStatus, /*mailType: MAIL_TYPE.GROUPMAIL*/});
        }
        return mails;
    }

    /**
     * 查询有奖励的邮件
     * @param roleId 
     * @param lean 
     */
    public static async findRewardsMails(roleId: string, lean = true) {
        const result: GroupMailType[] = await GroupMailModel.find({ roleStatus: { $elemMatch:{roleId, status:{ $in: [ MAIL_STATUS.CREATE, MAIL_STATUS.READ ] }} }, sendTime:{$lte: nowSeconds()} }).lean(lean);
        return result;
    }
}

export const GroupMailModel = getModelForClass(GroupMail);

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