import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, Ref } from '@typegoose/typegoose';
import Role, { RoleType } from './Role';
import Guild, { GuildType } from './Guild';
import { GUILD_APPLY_TYPE, GUILD_PER_PAGE } from '../consts';
import { genCode } from '../pubUtils/util';

@index({ applyCode: 1 })
@index({ guildCode: 1 })
@index({ roleId: 1 })
export default class UserGuildApply extends BaseModel {
    @prop({ required: true })
    applyCode: string;            // 唯一code 

    @prop({ required: true })
    roleId: string;               // 玩家id

    @prop({ required: true })
    role:  Ref<Role>;

    @prop({ required: true })
    guildCode: string;              // 公会唯一code
    
    @prop({ required: true })
    guild:  Ref<Guild>;

    @prop({ required: true, enum: GUILD_APPLY_TYPE, select: false})
    type: number;

    // 创建申请或邀请
    public static async createUserGuildApply(role: RoleType, guild: GuildType, type: number) {
        const applyCode = genCode(10);
        const result: UserGuildApplyType = await UserGuildApplyModel.findOneAndUpdate(
            { roleId: role.roleId, guildCode: guild.code, type  }, 
            { $set: { roleId: role.roleId, role: role._id, guildCode: guild.code, guild: guild._id }, $setOnInsert: { applyCode }
        }, { upsert: true, new: true })
        .select('applyCode guild')
        .populate({
            path: 'guild',
            select: 'code icon name lv memberCnt leader ceLimit',
            model: 'Guild',
            populate: {
                path: 'leader',
                select: 'roleName',
                model: 'Role'
            }
        })
        .lean();
        
        return result;
    }

    // 删除玩家发出的所有申请
    public static async deleteApply(roleId: string) {
        const result = await UserGuildApplyModel.deleteMany({ roleId });
        return result;
    }

    // 删除公会收到的所有申请
    public static async deleteApplyByGuild(guildCode: string) {
        const result = await UserGuildApplyModel.deleteMany({ guildCode, type: GUILD_APPLY_TYPE.APPLY });
        return result;
    }

    // 根据唯一code批量删除
    public static async deleteByApplyCode(applyCodeList: string[]) {
        const result = await UserGuildApplyModel.deleteMany({ applyCode: { $in: applyCodeList} });
        return result;
    }

    // 根绝唯一code查询申请或邀请
    public static async findByCode(applyCode: string) {
        const userGuildApply: UserGuildApplyType = await UserGuildApplyModel.findOne({ applyCode }).lean();
        return userGuildApply;
    }

    // 查询用户的申请列表
    public static async findApplyByRole(roleId: string) {
        const userGuildApply: UserGuildApplyType[] = await UserGuildApplyModel.find({ roleId, type: GUILD_APPLY_TYPE.APPLY }).lean();
        return userGuildApply;
    }

    // 根据唯一code查询申请或邀请
    public static async getListByApplyCode(applyCodeList: string[]) {
        const userGuildApply: UserGuildApplyType[] = await UserGuildApplyModel.find({ applyCode: { $in: applyCodeList}, type: GUILD_APPLY_TYPE.APPLY }).lean();
        return userGuildApply;
    }

    // 查询公会收到的申请
    public static async findApplyByGuild(code: string, lastApplyCode: string) {
        let condition = { guildCode: code, type: GUILD_APPLY_TYPE.APPLY };
        if(lastApplyCode) {
            const lastApply = await this.findByCode(lastApplyCode);
            condition["createdAt"] = { $lt: lastApply.createdAt };
        }
        const list: UserGuildApplyType[] = await UserGuildApplyModel.find(condition)
        .sort({ createdAt: -1 })
        .select('applyCode role')
        .populate('role', 'roleId roleName ce head frame spine heads frames spines lv title job quitTime', 'Role')
        .limit(GUILD_PER_PAGE).lean({ getters: true, virtuals: true });
        return list
    }

    // 查询玩家的邀请列表
    public static async findInviteByRole(roleId: string, lastApplyCode: string) {
        let condition = { roleId, type: GUILD_APPLY_TYPE.INVITE };
        if(lastApplyCode) {
            const lastApply = await this.findByCode(lastApplyCode);
            condition["createdAt"] = { $lt: lastApply.createdAt };
        }
        const list: UserGuildApplyType[] = await UserGuildApplyModel.find(condition, {_id: 0})
        .sort({ createdAt: -1 })
        .select('applyCode guild')
        .populate({
            path: 'guild',
            select: 'code icon name lv memberCnt leader ceLimit',
            model: 'Guild',
            populate: {
                path: 'leader',
                select: 'roleName',
                model: 'Role'
            }
        })
        .limit(GUILD_PER_PAGE).lean();
        return list
    }
}

export const UserGuildApplyModel = getModelForClass(UserGuildApply);

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