import dayjs from 'dayjs'
import CryptoJS from 'crypto-js'

/**
 * 日期格式化
 * @param date 日期
 * @param format 格式
 * @returns 格式化后的日期字符串
 */
export const formatDate = (date: Date | string, format = 'YYYY-MM-DD HH:mm:ss') => {
  return dayjs(date).format(format)
}

/**
 * MD5 加密
 * @param str 待加密字符串
 * @returns MD5 值
 */
export const md5 = (str: string) => {
  return CryptoJS.MD5(str).toString()
}

/**
 * AES 加密
 * @param data 待加密数据
 * @param key 密钥
 * @returns 加密后的字符串
 */
export const aesEncrypt = (data: string, key: string) => {
  return CryptoJS.AES.encrypt(data, key).toString()
}

/**
 * AES 解密
 * @param encrypted 加密字符串
 * @param key 密钥
 * @returns 解密后的字符串
 */
export const aesDecrypt = (encrypted: string, key: string) => {
  return CryptoJS.AES.decrypt(encrypted, key).toString(CryptoJS.enc.Utf8)
}

/**
 * 防抖函数
 * @param fn 目标函数
 * @param delay 延迟时间
 * @returns 防抖后的函数
 */
export const debounce = <T extends (...args: any[]) => any>(
  fn: T,
  delay: number
): ((...args: Parameters<T>) => void) => {
  let timer: NodeJS.Timeout
  
  return (...args: Parameters<T>) => {
    clearTimeout(timer)
    timer = setTimeout(() => fn(...args), delay)
  }
}

/**
 * 节流函数
 * @param fn 目标函数
 * @param interval 间隔时间
 * @returns 节流后的函数
 */
export const throttle = <T extends (...args: any[]) => any>(
  fn: T,
  interval: number
): ((...args: Parameters<T>) => void) => {
  let lastTime = 0
  
  return (...args: Parameters<T>) => {
    const now = Date.now()
    if (now - lastTime >= interval) {
      lastTime = now
      fn(...args)
    }
  }
}

/**
 * 深拷贝
 * @param obj 目标对象
 * @returns 拷贝后的对象
 */
export const deepClone = <T>(obj: T): T => {
  if (obj === null || typeof obj !== 'object') {
    return obj
  }
  
  if (Array.isArray(obj)) {
    return obj.map(item => deepClone(item)) as T
  }
  
  const cloned = {} as T
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      cloned[key] = deepClone(obj[key])
    }
  }
  
  return cloned
}

export default {
  formatDate,
  md5,
  aesEncrypt,
  aesDecrypt,
  debounce,
  throttle,
  deepClone
}
