import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';

function genCodeTmp(len) {
  const chars = '123456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijklmnopqrstuvwxyz';
  const charArr = chars.split('');
  let code = '';
  for (let i = 0; i < len; i++) {
    code += charArr[Math.floor(Math.random() * charArr.length)];
  }
  return code;
}



/**
  * 天梯派遣记录表
  */
@index({ roleId: 1, status: 1 })
@index({ batchCode: 1 })
export default class TowerTaskRec extends BaseModel {
  @prop({ required: true })
  roleId: string; // 角色 id
  @prop({ required: true })
  roleName: string; // 角色名

  @prop({ required: true})
  batchCode: string; // 本批派遣任务唯一标识
  @prop({ required: true, default: 0})
  status: number; // 派遣任务当前状态，0-可派遣，1-已派遣，2-已完成，3-已领取
  @prop({ required: true, default: 1})
  refreshStatus: number; // 派遣任务是否显示 -1-刷掉 0-隐藏 1-显示
  @prop({ required: true, type: Number, default: [] })
  heroes: Array<number>; // 此批派遣使用的全部武将

  @prop({ required: true})
  taskId: number; // 任务唯一 Id，来自任务表
  @prop({ required: true })
  taskCode: string; // 服务器生成的任务唯一编号
  @prop({ required: false })
  sendTime: Date; // 派遣时间
  @prop({ required: false })
  completeTime: Date; // 派遣结束时间

  public static async getCurTasks(roleId: string, lean = true) {
    const recs: TowerTaskRecType[] = await TowerTaskRecModel.find({roleId, refreshStatus: 1}).sort({createdAt: 1}).lean(lean);
    return recs;
  }

  public static async createTasks(roleId: string, roleName: string, batchCode: string, taskIds: Array<number>, refreshStatus: number) {
    const tasksData = taskIds.map(id => {
      const taskModel = new TowerTaskRecModel();
      const taskCode = genCodeTmp(6);
      const taskData = Object.assign(taskModel.toJSON(), {batchCode, taskId: id, taskCode, roleId, roleName, refreshStatus});
      return taskData;
    });
    const recs = await TowerTaskRecModel.insertMany(tasksData, {ordered: false});
    return recs;
  }

  public static async getTasksByCode(batchCode: string, lean = true) {
    const recs: TowerTaskRecType[] = await TowerTaskRecModel.find({batchCode}).lean(lean);
    return recs;
  }

  public static async sendHeroes(_roleId: string, batchCode: string, tasks: Array<{taskCode:string, heroes: Array<number>, completeTime: number}>, sendTime: Date, lean = true) {
    let recs = new Array();
    for (let {taskCode, heroes, completeTime} of tasks) {
      const rec: TowerTaskRecType = await TowerTaskRecModel.findOneAndUpdate(
        {batchCode, taskCode: taskCode, refreshStatus: 1},
        {heroes: heroes, status: 1, sendTime, completeTime: new Date(sendTime.getTime() + completeTime * 1000)},
        {new: true}).lean(lean);

      recs.push(rec);
    }
    return recs;
  }

  public static async finishTask(batchCode: string, tasks: Array<string>, _lean = true) {
    const recs:{ok: number, n:number, nModified:number} = await TowerTaskRecModel.updateMany({batchCode, taskCode: {$in:tasks}}, {status: 3, refreshStatus: -1});
    return recs;
  }

  // 将隐藏的任务显示出来 0=>1
  public static async showTask(roleId: string, batchCode: string, num: number, _lean = true) {
    const recs:{ok: number, n:number, nModified:number} = await TowerTaskRecModel.updateMany({roleId, refreshStatus: 0}, {batchCode, refreshStatus: 1}).sort({createdAt: 1}).limit(num);
    return recs;
  }
  // 刷掉旧任务 1=>-1
  public static async hideTask(roleId: string, taskIds: Array<string>, _lean = true) {
    // console.log(refTime)
    const recs:{ok: number, n:number, nModified:number} = await TowerTaskRecModel.updateMany({roleId, taskCode: {$in: taskIds}, refreshStatus: 1}, {refreshStatus: -1});
    return recs;
  }

  public static async updateBatchCode(roleId: string, taskIds: Array<string>, batchCode: string, _lean = true) {
    const recs:{ok: number, n:number, nModified:number} = await TowerTaskRecModel.updateMany({roleId, taskCode: {$in: taskIds}}, {batchCode});
    return recs;
  }

  public static async deleteAccount(roleId: string) {
    let result = await TowerTaskRecModel.deleteMany({roleId});
    return result;
  }
}

export const TowerTaskRecModel = getModelForClass(TowerTaskRec);

export interface TowerTaskRecType extends Pick<DocumentType<TowerTaskRec>, keyof TowerTaskRec>{};