import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';
import { getZeroPointD } from '../pubUtils/timeUtil';
import { SHOP_REFRESH_TYPE } from '../consts';

/**
  * 玩家购买商店记录表，每个商品一条，每次刷新新建一条
**/
@modelOptions({ schemaOptions: { id: false } })
@index({ roleId: 1 })

export default class UserTask extends BaseModel {

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

    @prop({ required: true, default: 1  })
    mainTaskStage: number;			// 主线所处在的阶段

    @prop({ required: true })
    dailyTaskRef: Date;  		// 每日任务的每周刷新时间

    @prop({ required: true, default: 0 })
    dailyTaskPoint: number;  		// 每日任务的累计积分

    @prop({ required: true })
    dailyTaskRefWeekly: Date;  		// 每日任务的每周刷新时间

    @prop({ required: true, default: 0 })
    dailyTaskPointWeekly: number;  	// 每日任务的每周活跃积分

    @prop({ required: true, type: Number, default: [] })
    dailyTaskBox: number[];  	    // 每日任务每周已领取箱子

    @prop({ required: true, default: 0 })
    achievementPoint: number;  		// 成就积分

    @prop({ required: true, type: Number, default: []  })
    achievementBox: number[];  		// 成就已领取了的箱子

    
    public static async findByRole(roleId: string) {
      let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, { $setOnInsert: {
        mainTaskStage: 1, dailyTaskPoint: 0, dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: 0, dailyTaskBox: [], achievementPoint: 0, achievementBox: []
      } }, { new: true, upsert: true }).lean();
      return rec;
    }

    public static async resetDailyScore(roleId: string, point: number, curWeek: Date) {
      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, { 
        $set: { dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: point, dailyTaskBox: [] },
        $inc: { dailyTaskPoint: point }
      }, { new: true }).lean();
      return rec;
    }

    public static async incInfo(roleId: string, inc: UserTaskIncParam) {
      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, {
        $inc: inc
      }, { new: true }).lean();
      return rec;
    }

    public static async updateInfo(roleId: string, update: UserTaskParam) {
      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, {
        $set: update
      }, { new: true }).lean();
      return rec;
    }

    public static async decreaseDailyPoint(roleId: string, point: number) {
      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate( { roleId, dailyTaskPoint: { $gte: point }}, { $inc: { dailyTaskPoint: -point } }, { new: true }).lean();
      return rec;
    }

    public static async pushDailyBox(roleId: string, id: number, curWeek: Date, shouldRefresh: boolean) {
      let rec: UserTaskType;
      if(shouldRefresh) {
        rec = await UserTaskModel.findOneAndUpdate({ roleId }, {
          $set: { dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: 0, dailyTaskBox: [ id ] }
        }, { new: true }).lean()
      } else {
        rec = await UserTaskModel.findOneAndUpdate({ roleId }, { $push: { dailyTaskBox: id } }, { new: true }).lean();
      }
      return rec;
    }

    public static async refreshWeekly(roleId: string, debug = false) {
      let curWeek = getZeroPointD(SHOP_REFRESH_TYPE.WEEKLY);
      let condition = { roleId };
      if(!debug) {
        condition['dailyTaskRefWeekly'] = { $lt: curWeek }
      }

      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate(condition, {
        $set: { dailyTaskRefWeekly: curWeek, dailyTaskPointWeekly: 0, dailyTaskBox: [] }
      }, { new: true }).lean();
      return rec;
    }

    public static async pushAchievementBox(roleId: string, id: number) {
      let rec = await UserTaskModel.findOneAndUpdate({ roleId }, { $push: { achievementBox: id } }, { new: true }).lean();
      return rec;
    }

    public static async setRefDaily(roleId: string) {
      let rec: UserTaskType = await UserTaskModel.findOneAndUpdate({ roleId }, {
        $set: { dailyTaskRef: new Date() }
      }, { new: true }).lean();
      return rec;
    }
}

export const UserTaskModel = getModelForClass(UserTask);

export interface UserTaskType extends Pick<DocumentType<UserTask>, keyof UserTask> { }
export type UserTaskParam = Partial<UserTaskType>;
export type UserTaskIncParam = Pick<UserTaskParam, 'mainTaskStage'|'dailyTaskPoint'|'dailyTaskPointWeekly'|'achievementPoint'>;
