import { sm2 } from 'sm-crypto'
import CryptoJS from 'crypto-js'

export class SmCrypto {
  private readonly privateKey: string
  private readonly publicKey: string
  constructor(privateKey: string, publicKey: string) {
    this.privateKey = privateKey
    this.publicKey = publicKey
  }

  doEncrypt(formData) {
    const requestFormData = {
      basicData: {
        timeStamp: this.getNowFormatDate(),
        messageId: this.getUUID(),
      },
      bizData: formData,
    }
    const encryptData = sm2.doEncrypt(JSON.stringify(requestFormData), this.publicKey)
    const encryptRequestFormData = {
      encryptData,
      identifying: this.sha256(encryptData),
    }
    return encryptRequestFormData
  }

  sha256(data) {
    return CryptoJS.SHA256(data).toString()
  }

  doDecrypt(responseFormData) {
    if (responseFormData.identifying === this.sha256(responseFormData.encryptData)) {
      return JSON.parse(sm2.doDecrypt(responseFormData.encryptData, this.privateKey))
    } else {
      return {
        code: 100003,
        data: null,
        msg: 'validation failed',
      }
    }
  }

  getNowFormatDate() {
    const date = new Date()
    const month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1
    const strDate = date.getDate() < 10 ? '0' + date.getDate() : date.getDate()
    const hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
    const minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()
    const seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()
    return `${date.getFullYear()}${month}${strDate}${hours}${minutes}${seconds}`
  }

  uuid(len, radix) {
    const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
    const uuid = []
    let i
    radix = radix || chars.length

    if (len) {
      for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)]
    } else {
      let r
      uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
      uuid[14] = '4'
      for (i = 0; i < 36; i++) {
        if (!uuid[i]) {
          r = 0 | (Math.random() * 16)
          uuid[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r]
        }
      }
    }

    return uuid.join('')
  }

  getUUID() {
    return this.uuid(36, 16)
  }
}
