import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, ReturnModelType, mongoose } from '@typegoose/typegoose';
import { CounterAllModal } from './CounterAll';
import { COUNTER } from '../consts';
import { ActivityModel } from './Activity';

/**
  * 活动合集
*/
@index({ activityId: 1 })

export default class Activity_Group extends BaseModel {
    @prop({ required: true })
    groupId: number;				// 组Id
    @prop({ required: true })
    groupName: string;				// 组名
    @prop({ required: true, type: Number })
    activities: number[];		    // 活动Id
    @prop({ required: true })
    beginTime: Date;			    // 里面的activity的最早的时间
    @prop({ required: true })
    endTime: Date;					// 里面的activity的最晚的时间
    @prop({ required: true, type: Number })
    serverIds: number[];			// 关联服务器列表
    @prop({ required: true, default: 0 })
    type: number;				    // 类型 ACTIVITY_GROUP_TYPE


    //查询组
    public static async createGroup(uid = 1) {
        let groupId = await CounterAllModal.getNewCounter(COUNTER.ACTIVITY_GROUP);

        let result: ActivityGroupModelType = await ActivityGroupModel.findOneAndUpdate({ groupId }, {
            $setOnInsert: { groupName: `活动组${groupId}`, activities: [], serverIds: [], createdBy: uid, type: 0 }, $set: { updatedBy: uid }
        }, { new: true, upsert: true }).lean();
        return result;
    }

    public static async findByServerId(serverId: number) {
        let result: ActivityGroupModelType[] = await ActivityGroupModel.find({ serverIds: serverId }).lean();
        return result;
    }

    public static async findByActivity(activityId: number) {
        let result: ActivityGroupModelType[] = await ActivityGroupModel.find({ activities: activityId }).lean();
        return result;
    }
    //查询组
    public static async findGroupsData(groupIds: number[]) {
        let result: ActivityGroupModelType[] = await ActivityGroupModel.find({ groupId: { $in: groupIds } }).lean();
        return result;
    }

    //查询组
    public static async findGroupData(groupId: number) {
        let result: ActivityGroupModelType = await ActivityGroupModel.findOne({ groupId }).lean();
        return result;
    }

    //更新名字
    public static async updateGroup(groupId: number, update: ActivityGroupModelTypeParam, uid = 1) {
        let result: ActivityGroupModelType = await ActivityGroupModel.findOneAndUpdate({ groupId },
            { $set: { ...update, updatedBy: uid } }, { new: true }).lean(true);
        return result;
    }

    //更新询组
    public static async setActivitiesToGroupData(groupId: number, activities: number[], uid = 1) {
        await this.pullByActivityIds(activities, uid); // 先将原先的删除
        let result: ActivityGroupModelType = await ActivityGroupModel.findOneAndUpdate({ groupId },
            { $set: { activities, updatedBy: uid } }, { new: true }).lean(true);
        await ActivityModel.updateGroupId(activities, groupId, uid);
        result = await this.updateTime(result.groupId, result.activities, uid);
        return result;
    }

    //更新询组
    public static async addActivitiesToGroupData(groupId: number, activities: number[], uid = 1) {
        await this.pullByActivityIds(activities, uid); // 先将原先的删除
        let result: ActivityGroupModelType = await ActivityGroupModel.findOneAndUpdate({ groupId },
            { $addToSet: { activities: { $each: activities } } }, { new: true }).lean(true);
        await ActivityModel.updateGroupId(activities, groupId, uid);
        result = await this.updateTime(result.groupId, result.activities, uid);
        return result;
    }

    //更新询组
    public static async addServerToGroupData(serverId: number, groupIds: number[]) {
        await ActivityGroupModel.updateMany({ groupId: { $in: groupIds} },
            { $addToSet: { serverIds: serverId } }, { new: true }).lean(true);
    }

    // 根据包含的活动更新开始和结束时间
    private static async updateTime(groupId: number, aids: number[], uid = 1) {
        let activities = await ActivityModel.findActivityByIds(aids);
        let beginTime = undefined, endTime = undefined;
        for (let activity of activities) {
            if (!beginTime || activity.beginTime < beginTime) beginTime = activity.beginTime;
            if (!endTime || activity.endTime > endTime) endTime = activity.endTime;
        }
        let result: ActivityGroupModelType = await ActivityGroupModel.findOneAndUpdate({ groupId },
            { $set: { beginTime, endTime, updatedBy: uid } }, { new: true }).lean(true);
        return result;
    }


    // 删除活动id
    public static async pullByActivityIds(activities: number[], uid = 1) {
        await ActivityModel.updateGroupId(activities, 0, uid);
        let activityGroups = await ActivityGroupModel.find({ activities: { $in: activities } });
        for (let { groupId } of activityGroups) {
            let result = await ActivityGroupModel.findOneAndUpdate({ groupId }, { $pull: { activities: { $in: activities } }, $set: { updatedBy: uid } }, { new: true }).lean(true);
            await this.updateTime(result.groupId, result.activities);
        }
    }


    //更新服务器
    public static async updateServerData(groupId: number, serverIds: number[], uid = 1) {
        let result: ActivityGroupModelType = await ActivityGroupModel.findOneAndUpdate({ groupId },
            { $set: { serverIds, updatedBy: uid } }, { new: true }).lean(true);
        return result;
    }

    //获取所有活动组
    public static async findAllActivityGroup() {
        let result: ActivityGroupModelType[] = await ActivityGroupModel.find({}).lean();
        return result;
    }

    //删除组
    public static async deleteGroup(groupId: number) {
        let result = await ActivityGroupModel.deleteMany({ groupId });
        return result;
    }

    //查询
    public static async findByCondition(page: number, pageSize: number, serverId: number = 0, current: boolean = false, groupId: number = 0) {
        let searchObj = {};
        if (serverId != 0) searchObj['serverIds'] = { $elemMatch: { $eq: serverId } };
        if (groupId != 0) searchObj['groupId'] = groupId;
        if (current) {
            searchObj['beginTime'] = { $lte: new Date };
            searchObj['endTime'] = { $gte: new Date };
        }
        const result: ActivityGroupModelType[] = await ActivityGroupModel.find(searchObj, { _id: 0 }).limit(pageSize).skip((page - 1) * pageSize).sort({ updatedAt: -1 }).lean();
        return result;
    }

    // 获得活动数量
    public static async countByCondition(serverId: number = 0, current: boolean = false, groupId: number = 0) {
        let searchObj = {};
        if (serverId != 0) searchObj['serverId'] = { $in: [serverId] };
        if (groupId != 0) searchObj['groupId'] = groupId;
        if (current) {
            searchObj['beginTime'] = { $lte: new Date };
            searchObj['endTime'] = { $gte: new Date };
        }
        const result = await ActivityGroupModel.count(searchObj);
        return result;
    }

    public static async findAllActivityGroups() {
        let all: ActivityGroupModelType[] = [];
        let createdAt;
        for(let i = 0; i < 9999; i++) { // 防死循环
            let condition = {};
            if(createdAt) condition['createdAt'] = { $gt: createdAt }
            let cur = await ActivityGroupModel.find(condition).limit(1000).sort({ createdAt: 1 }).lean();
            if(cur.length == 0) break;
            createdAt = cur[cur.length - 1].createdAt;
            all.push(...cur);
        }
        return all;
    }
}

export let ActivityGroupModel: ReturnModelType<typeof Activity_Group, {}>;
export function loadActivityGroup(connect: mongoose.Connection) {
    ActivityGroupModel = getModelForClass(Activity_Group, {
        existingConnection: connect
    });
}

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