const crypto = require('crypto');
const CryptoJS = require('crypto-js');

export function md5(text: string) {
  return crypto.createHash('md5').update(text).digest('hex');
}

// https://segmentfault.com/a/1190000039192480
/**
 * AES-256-ECB对称加密
 * @param text {string} 要加密的明文
 * @param secretKey {string} 密钥，43位随机大小写与数字
 * @returns {string} 加密后的密文，Base64格式
 */
export function AES_ECB_ENCRYPT(text: string, secretKey: string): string {
  const keyHex = CryptoJS.enc.Base64.parse(secretKey);
  const messageHex = CryptoJS.enc.Utf8.parse(text);
  const encrypted = CryptoJS.AES.encrypt(messageHex, keyHex, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7,
  });
  return encrypted.toString();
}

/**
 * AES-256-ECB对称解密
 * @param textBase64 {string} 要解密的密文，Base64格式
 * @param secretKey {string} 密钥，43位随机大小写与数字
 * @returns {string} 解密后的明文
 */
export function AES_ECB_DECRYPT(textBase64: string, secretKey: string): string {
  const keyHex = CryptoJS.enc.Base64.parse(secretKey);
  const decrypt = CryptoJS.AES.decrypt(textBase64, keyHex, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7,
  });
  return CryptoJS.enc.Utf8.stringify(decrypt);
}

export function addFieldIfExist(
  name: string,
  value: any,
  obj: any,
  anthor: any = undefined,
) {
  if (value !== undefined) {
    if (anthor !== undefined) {
      obj[name] = anthor;
    } else {
      obj[name] = value;
    }
  }
  return obj;
}

/**
 * AES 加密
 * @param {string} data - 要加密的数据
 * @param {string} key - 加密密钥（16/24/32 字节，对应 AES-128/192/256）
 * @param {string} iv - 初始化向量（16 字节）
 * @param {string} algorithm - 加密算法，默认为 'aes-256-cbc'
 * @param {string} outputEncoding - 输出编码，默认为 'base64'
 * @returns {string} - 加密后的数据
 */
export function AES_CBC_ENCRYPT(
  data,
  key,
  iv,
  algorithm = 'aes-256-cbc',
  outputEncoding = 'base64',
) {
  // 验证输入
  if (!data || !key || !iv) {
    throw new Error('数据、密钥和初始化向量不能为空');
  }

  const keyFromHex = Buffer.from(key, 'hex');
  const ivFromHex = Buffer.from(iv, 'hex');

  if (ivFromHex.length !== 16) {
    throw new Error('AES IV 必须是 16 字节');
  }

  // 创建加密器
  const cipher = crypto.createCipheriv(algorithm, keyFromHex, ivFromHex);

  // 更新加密内容
  let encrypted = cipher.update(data, 'utf8', outputEncoding);
  encrypted += cipher.final(outputEncoding);

  return encrypted;
}

/**
 * AES 解密
 * @param {string} encryptedData - 加密的数据
 * @param {string} key - 解密密钥（必须与加密时使用的相同）
 * @param {string} iv - 初始化向量（必须与加密时使用的相同）
 * @param {string} algorithm - 解密算法，默认为 'aes-256-cbc'
 * @param {string} inputEncoding - 输入编码，默认为 'base64'
 * @returns {string} - 解密后的数据
 */
export function AES_CBC_DECRYPT(
  encryptedData,
  key,
  iv,
  algorithm = 'aes-256-cbc',
  inputEncoding = 'base64',
) {
  // 验证输入
  if (!encryptedData || !key || !iv) {
    throw new Error('加密数据、密钥和初始化向量不能为空');
  }

  const keyFromHex = Buffer.from(key, 'hex');
  const ivFromHex = Buffer.from(iv, 'hex');
  if (ivFromHex.length !== 16) {
    throw new Error('AES IV 必须是 16 字节');
  }
  // 创建解密器
  const decipher = crypto.createDecipheriv(algorithm, keyFromHex, ivFromHex);

  // 更新解密内容
  let decrypted = decipher.update(encryptedData, inputEncoding, 'utf8');
  decrypted += decipher.final('utf8');

  return decrypted;
}

/**
 * 生成随机密钥
 * @param {number} length - 密钥长度（字节），默认为 32（对应 AES-256）
 * @returns {string} - 十六进制格式的密钥
 */
export function generateKey(length = 32) {
  return crypto.randomBytes(length).toString('hex');
}

/**
 * 生成随机初始化向量
 * @returns {string} - 十六进制格式的初始化向量
 */
export function generateIV() {
  return crypto.randomBytes(16).toString('hex');
}
