import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType } from '@typegoose/typegoose';
import { generateNum, aesEncryptcfb, aesDecryptcfb } from '../pubUtils/util';
import { ENCRYPT_KEY, ENCRYPT_IV } from './../consts';

const moment = require('moment');

/**
  * 短信字段接口
*/
@index({ tel: 1 })
export default class Sms extends BaseModel {

  @prop({ required: true, set: (val: string) => aesEncryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV), get: (val: string) => aesDecryptcfb(val, ENCRYPT_KEY, ENCRYPT_IV)  })
  tel: string;

  @prop({ required: true })
  telHash: string;

  @prop({ required: true })
  code: string;

  @prop({ required: true })
  used: boolean;

  @prop({ required: true })
  updateTime: Date;

  @prop({ required: true })
  countToday: number;

  @prop({ required: true })
  isFixed: boolean;

  public static async findByTel(tel: string, lean = true) {
    const sms: SmsType = await smsModel.findOne({ tel }).lean(lean);
    return sms;
  }

  public static async updateByTel(tel: string, code: string, used: boolean, updateTime: Date, countToday: number) {

    const sms: SmsType = await smsModel.findOneAndUpdate({ tel }, { tel, code, used, updateTime, countToday }, { upsert: true }).lean({ getters: true });
    return sms;
  }

  public static async validateSms(tel: string, code: string) {
    const record: SmsType = await smsModel.findOneAndUpdate({ tel, code, used: false }, { used: true }).lean({ getters: true });
    return !!record;
  }

  public async timeLimit(interval: number) {
    if (Date.now() > this.updateTime.getTime() + interval) {
      return false;
    }
    return true;
  }

  public async cntLimit(cnt: number) {
    console.log('hasSendToday:', this.hasSendToday(), this.countToday, cnt);
    if (this.hasSendToday() && this.countToday >= cnt) {
      return true;
    }
    this.countToday = 0;
    return false;
  }

  public hasSendToday() {
    // console.log(moment(this.updateTime).format('YYYY-MM-DD'), moment(Date.now()).format('YYYY-MM-DD'));
    return moment(this.updateTime).format('YYYY-MM-DD') === moment(Date.now()).format('YYYY-MM-DD');
  }

  public static async fixSms(tel: string) {

    const sms: SmsType = await smsModel.findOneAndUpdate({ tel }, { $setOnInsert: {
      tel,
      code: generateNum(6), 
      used: false,
      updateTime: new Date(),
      countToday: 1
    }, $set: { isFixed: true } }, {new: true, upsert: true}).lean({ getters: true });
    return sms;
  }
}

export const smsModel = getModelForClass(Sms);

export interface SmsType extends Pick<DocumentType<Sms>, keyof Sms>{};