import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, ReturnModelType, mongoose } from '@typegoose/typegoose';
import { CounterAllModal } from './CounterAll';
import { COUNTER } from '../consts';
import { ActivityGroupModel } from './ActivityGroup';
import { UpdateActivityParam } from '../domain/backEndField/params';

class MultiTime {
    @prop({ required: true })
    id: number;			    // 开启时间  timeType=4
    @prop({ required: true })
    beginTime: Date;			    // 开启时间  timeType=4
    @prop({ required: true })
    endTime: Date;					// 结束时间  timeType=4
}

/**
  * 活动系统 
*/
@index({ activityId: 1 })
@index({ type: 1 })

export default class Activity extends BaseModel {
    @prop({ required: true })
    groupId: number;				// 组Id
    @prop({ required: true })
    activityId: number;				// 活动Id
    @prop({ required: true })
    beginTime: Date;			    // 开启时间  timeType=3
    @prop({ required: true })
    endTime: Date;					// 结束时间  timeType=3
    @prop({ required: true })
    type: number;					// 活动类型
    @prop({ required: true })
    data: string;					// 活动表中的数据
    @prop({ required: true })
    name: string;                   // 活动名
    @prop({ required: true, type: MultiTime, _id: false })
    multiTime: MultiTime[];					// 结束时间  timeType=4
    
    @prop({ required: true })
    timeType: number;			    // 活动时间类型 ACTIVITY_TIME_TYPE 1.服务器开启时间 2.角色创建时间 3.指定开启时间(beginTime,endTime)
    @prop({ required: true })
    days: number;					// 活动持续天数 timeType=1、2
    @prop({ required: true })
    effectDay: number;			    // 循环中显示的天数
    @prop({ required: true })
    delayDay: number;			    // 迟几天开启活动，0表示按照规定时间开启
    @prop({ required: true })
    interval: number;			    // 周期性活动时间间隔,天
    @prop({ required: true })
    hideDayByServer: number;			    // 开服后几天内该活动不可见

    @prop({ required: true })
    isEnable: boolean;			    // 该活动是否有效

    // 获取正在开启和即将到来的活动列表
    public static async findOpenAndComingActivityes() {
        let result: ActivityModelType[] = await ActivityModel.find({ isEnable: true }).lean();
        return result;
    }

    //根据活动类型查询开启的活动数据
    public static async findOpenActivityByType(activityGroupId: number[], type: number) {
        let result: ActivityModelType[] = await ActivityModel.find(
            { groupId: { $in: activityGroupId }, type, isEnable: true }
        ).sort({ activityId: -1 }).lean(true);
        return result;
    }

    //根据活动类型查询开启的活动数据
    public static async findOpenActivityByTypes(activityGroupId: number[], types: number[]) {
        let result: ActivityModelType[] = await ActivityModel.find(
            { groupId: { $in: activityGroupId }, type: { $in: types }, isEnable: true }
        ).sort({ activityId: -1 }).lean(true);
        return result;
    }


    public static async findOpenActivityByGroupId(activityGroupId: number[]) {
        let result: ActivityModelType[] = await ActivityModel.find(
            { groupId: { $in: activityGroupId }, isEnable: true }
        ).sort({ activityId: -1 }).lean(true);
        return result;
    }

    //根据活动类型查询活动数据
    public static async findActivityByType(type: number) {
        let result: ActivityModelType[] = await ActivityModel.find({ type }).lean(true);
        return result;
    }

    //debug测试用接口
    public static async debugFindActivityByType(type: number) {
        let result: ActivityModelType[] = await ActivityModel.findOne({ type }).lean(true);
        return result;
    }

    //根据活动id查询活动数据
    public static async findActivity(activityId: number) {
        let result: ActivityModelType = await ActivityModel.findOne({ activityId }).lean(true);
        return result;
    }

    //新增活动
    public static async updateActivity(aids: number[], param: UpdateActivityParam, uid = 1) {
        let result: ActivityModelType[] = [];
        let newAids = [];
        for (let activityId of aids) {
            if (!activityId) activityId = await CounterAllModal.getNewCounter(COUNTER.ACTIVITY);
            newAids.push(activityId);
            if (!param.beginTime) {
                delete param["beginTime"];
            }
            if (!param.endTime) {
                delete param["endTime"];
            }
            if (!param.multiTime) {
                delete param["multiTime"];
            }
            let rec: ActivityModelType = await ActivityModel.findOneAndUpdate({ activityId }, { $set: { ...param, updatedBy: uid }, $setOnInsert: { isEnable: true, createdBy: uid } },
                { new: true, upsert: true }).lean(true);
            result.push(rec);
        }
        if (param.groupId != undefined) {
            let groupId = param.groupId;
            if (param.groupId == 0) {
                let newGroup = await ActivityGroupModel.createGroup(uid);
                groupId = newGroup.groupId;
            }
            await ActivityGroupModel.addActivitiesToGroupData(groupId, newAids, uid);
        }
        return result;
    }

    public static async setEnable(activityId: number, isEnable: boolean, uid = 1) {
        let result = await ActivityModel.findOneAndUpdate({ activityId }, { $set: { isEnable, uid } }, { new: true }).lean();
        return result;
    }

    //删除活动
    public static async deleteActivity(activityId: number, uid = 1) {
        let result = await ActivityModel.deleteMany({ activityId });
        await ActivityGroupModel.pullByActivityIds([activityId], uid);
        return result;
    }


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

    //查询
    public static async findByCondition(page: number, pageSize: number, sortField: string = 'updatedAt', sortOrder: string = 'descend', type: number = 0, groupId: number = 0, current: boolean = false, activityId: number = 0) {
        let searchObj = {};
        if (type != 0) searchObj['type'] = type;
        if (groupId != 0) searchObj['groupId'] = groupId;
        if (activityId != 0) searchObj['activityId'] = activityId;
        if (current) {
            searchObj['beginTime'] = { $lte: new Date };
            searchObj['endTime'] = { $gte: new Date };
        }
        let sort = {};
        if (sortField && sortOrder) {
            if (sortOrder == 'ascend') {
                sort[sortField] = 1;
            } else if (sortOrder == 'descend') {
                sort[sortField] = -1;
            }
        }
        const result: ActivityModelType[] = await ActivityModel.find(searchObj, { _id: 0 }).limit(pageSize).skip((page - 1) * pageSize).sort(sort).lean();
        return result;
    }

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

    //根据多个活动id查询活动数据
    public static async findActivityByIds(activityIds: number[]) {
        let result: ActivityModelType[] = await ActivityModel.find({ activityId: { $in: activityIds } }).lean();
        return result;
    }

    public static async updateGroupId(activityIds: number[], groupId: number, uid = 1) {
        let result = await ActivityModel.updateMany({ activityId: { $in: activityIds } }, { $set: { groupId, updatedBy: uid }, $setOnInsert: { createdBy: uid } });
        return result;
    }
}


export let ActivityModel: ReturnModelType<typeof Activity, {}>;
export function loadActivity(connect: mongoose.Connection) {
    ActivityModel = getModelForClass(Activity, {
        existingConnection: connect
    });
}

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