import CryptoJS from 'crypto-js'

/**
 * 增强版AES CFB加密解密工具
 * 采用CFB模式，无需填充，解决CBC模式填充问题
 */

// 配置接口
export interface AESConfig {
  key: string
  iv: string
  mode: typeof CryptoJS.mode.CFB
  padding: typeof CryptoJS.pad.NoPadding
}

// 加密结果接口
export interface EncryptResult {
  encryptedData: string
  iv: string
  timestamp: number
  version: string
}

// 后端使用的十六进制密钥和IV（与后端完全匹配）
const BACKEND_AES_KEY = "e36fa8396463df288532c5f1adc4c9fb960ec8decff0d2856cd94ad340638e6f"
const BACKEND_AES_IV = "1c16606009b8e3630ddbaeb06c831099"

// 默认配置
const DEFAULT_CONFIG: AESConfig = {
  key: BACKEND_AES_KEY,
  iv: BACKEND_AES_IV,
  mode: CryptoJS.mode.CFB,
  padding: CryptoJS.pad.NoPadding
}

/**
 * 密钥和IV处理函数
 * 后端使用十六进制格式，需要将十六进制字符串转换为字节数组
 */
function processKeyAndIV(config: AESConfig): { key: CryptoJS.lib.WordArray; iv: CryptoJS.lib.WordArray } {
  // 检查是否为十六进制字符串（后端格式）
  const isHexKey = /^[0-9a-fA-F]+$/.test(config.key)
  const isHexIV = /^[0-9a-fA-F]+$/.test(config.iv)

  if (isHexKey && isHexIV) {
    // 后端格式：十六进制字符串，直接解析为字节数组
    return {
      key: CryptoJS.enc.Hex.parse(config.key),
      iv: CryptoJS.enc.Hex.parse(config.iv)
    }
  } else {
    // 前端格式：字符串，使用UTF-8编码
    // 密钥处理：确保32字节长度
    const processedKey = config.key.padEnd(32, '0').substring(0, 32)

    // IV处理：确保16字节长度
    const processedIV = config.iv.padEnd(16, '0').substring(0, 16)

    return {
      key: CryptoJS.enc.Utf8.parse(processedKey),
      iv: CryptoJS.enc.Utf8.parse(processedIV)
    }
  }
}

/**
 * 验证配置有效性
 */
function validateConfig(config: AESConfig): void {
  if (!config.key || config.key.trim().length === 0) {
    throw new Error('AES密钥不能为空')
  }

  if (!config.iv || config.iv.trim().length === 0) {
    throw new Error('AES IV不能为空')
  }

  // 检查是否为十六进制格式
  const isHexKey = /^[0-9a-fA-F]+$/.test(config.key)
  const isHexIV = /^[0-9a-fA-F]+$/.test(config.iv)

  if (isHexKey && isHexIV) {
    // 十六进制格式：密钥应为64字符（32字节），IV应为32字符（16字节）
    if (config.key.length !== 64) {
      throw new Error('十六进制AES密钥长度必须为64字符（32字节）')
    }

    if (config.iv.length !== 32) {
      throw new Error('十六进制AES IV长度必须为32字符（16字节）')
    }
  } else {
    // 字符串格式：长度要求
    if (config.key.length < 16) {
      throw new Error('AES密钥长度至少16位')
    }

    if (config.iv.length < 16) {
      throw new Error('AES IV长度至少16位')
    }
  }
}

/**
 * 增强版AES加密函数
 * @param data 需要加密的数据
 * @param customConfig 自定义配置（可选）
 * @returns 加密结果对象
 */
export function enhancedEncrypt(data: string | object, customConfig?: Partial<AESConfig>): EncryptResult {
  try {
    if (!data) {
      throw new Error('加密数据不能为空')
    }

    // 合并配置
    const config: AESConfig = { ...DEFAULT_CONFIG, ...customConfig }

    // 验证配置
    validateConfig(config)

    // 处理密钥和IV
    const { key, iv } = processKeyAndIV(config)

    // 准备明文数据
    const plaintext = typeof data === 'object' ? JSON.stringify(data) : String(data)

    // 对数据进行UTF-8编码
    const srcs = CryptoJS.enc.Utf8.parse(plaintext)

    // 执行AES CFB加密
    const encrypted = CryptoJS.AES.encrypt(srcs, key, {
      iv: iv,
      mode: config.mode,
      padding: config.padding
    })

    // 返回完整的加密结果
    return {
      encryptedData: CryptoJS.enc.Base64.stringify(encrypted.ciphertext),
      iv: CryptoJS.enc.Base64.stringify(iv),
      timestamp: Date.now(),
      version: '3.0' // 更新版本号以标识CFB模式
    }

  } catch (error) {
    console.error('AES加密失败:', error)
    throw new Error(`加密失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

/**
 * 增强版AES解密函数
 * @param encryptedData 加密的Base64字符串
 * @param iv IV的Base64字符串
 * @param customConfig 自定义配置（可选）
 * @returns 解密后的原始数据
 */
export function enhancedDecrypt(encryptedData: string, iv: string, customConfig?: Partial<AESConfig>): string | object {
  try {
    if (!encryptedData || !iv) {
      throw new Error('解密数据或IV不能为空')
    }

    // 合并配置
    const config: AESConfig = { ...DEFAULT_CONFIG, ...customConfig }

    // 验证配置
    validateConfig(config)

    // 处理密钥
    const { key } = processKeyAndIV(config)

    // 解析IV
    const aesIv = CryptoJS.enc.Base64.parse(iv)

    // 执行AES CFB解密
    const decrypt = CryptoJS.AES.decrypt(encryptedData, key, {
      iv: aesIv,
      mode: config.mode,
      padding: config.padding
    })

    // 转换为UTF-8字符串
    const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)

    if (!decryptedStr) {
      throw new Error('解密失败，可能是密钥错误或数据损坏')
    }

    // 尝试解析为JSON对象，如果不是JSON则返回字符串
    try {
      return JSON.parse(decryptedStr)
    } catch {
      return decryptedStr
    }

  } catch (error) {
    console.error('AES解密失败:', error)
    throw new Error(`解密失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

/**
 * 加密敏感数据（业务专用）
 * @param sensitiveData 敏感数据对象
 * @returns 加密结果
 */
export function encryptSensitiveData(sensitiveData: object): EncryptResult {
  const dataToEncrypt = {
    ...sensitiveData,
    encryptedAt: new Date().toISOString(),
    version: '3.0',
    securityLevel: 'high'
  }

  return enhancedEncrypt(dataToEncrypt)
}

/**
 * 与后端完全匹配的加密函数
 * 使用后端相同的十六进制密钥和IV，确保加密解密完全匹配
 * @param plaintext 明文数据
 * @returns 加密后的Base64字符串
 */
export function encryptWithBackendConfig(plaintext: string): string {
  try {
    if (!plaintext) {
      throw new Error('加密数据不能为空')
    }

    // 使用后端配置
    const config: AESConfig = { ...DEFAULT_CONFIG }

    // 验证配置
    validateConfig(config)

    // 处理密钥和IV（十六进制格式）
    const { key, iv } = processKeyAndIV(config)

    // 对数据进行UTF-8编码
    const srcs = CryptoJS.enc.Utf8.parse(plaintext)

    // 执行AES CFB加密
    const encrypted = CryptoJS.AES.encrypt(srcs, key, {
      iv: iv,
      mode: config.mode,
      padding: config.padding
    })

    // 返回Base64编码的加密数据
    return CryptoJS.enc.Base64.stringify(encrypted.ciphertext)

  } catch (error) {
    console.error('后端匹配加密失败:', error)
    throw new Error(`加密失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

/**
 * 与后端完全匹配的解密函数
 * @param encryptedData 加密的Base64字符串
 * @returns 解密后的原始数据
 */
export function decryptWithBackendConfig(encryptedData: string): string {
  try {
    if (!encryptedData) {
      throw new Error('解密数据不能为空')
    }

    // 使用后端配置
    const config: AESConfig = { ...DEFAULT_CONFIG }

    // 验证配置
    validateConfig(config)

    // 处理密钥
    const { key, iv } = processKeyAndIV(config)

    // 执行AES CFB解密
    const decrypt = CryptoJS.AES.decrypt(encryptedData, key, {
      iv: iv,
      mode: config.mode,
      padding: config.padding
    })

    // 转换为UTF-8字符串
    const decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)

    if (!decryptedStr) {
      throw new Error('解密失败，可能是密钥错误或数据损坏')
    }

    return decryptedStr

  } catch (error) {
    console.error('后端匹配解密失败:', error)
    throw new Error(`解密失败: ${error instanceof Error ? error.message : '未知错误'}`)
  }
}

/**
 * 解密登录数据
 * @param loginData 登录数据对象
 * @returns 解密后的登录信息
 */
export function decryptLoginData(loginData: { aesPassword: string; saltValue: string }): any {
  try {
    // 使用saltValue作为IV进行解密
    return enhancedDecrypt(loginData.aesPassword, loginData.saltValue)
  } catch (error) {
    console.error('登录数据解密失败:', error)
    throw error
  }
}

/**
 * 验证加密数据完整性
 * @param encryptResult 加密结果
 * @returns 是否有效
 */
export function validateEncryptedData(encryptResult: EncryptResult): boolean {
  try {
    if (!encryptResult.encryptedData || !encryptResult.iv) {
      return false
    }

    // 检查时间戳是否合理（不超过24小时）
    const now = Date.now()
    const timeDiff = now - encryptResult.timestamp
    if (timeDiff > 24 * 60 * 60 * 1000) {
      return false
    }

    // 检查版本号（支持2.0和3.0版本）
    if (!encryptResult.version || (encryptResult.version !== '2.0' && encryptResult.version !== '3.0')) {
      return false
    }

    return true
  } catch {
    return false
  }
}

/**
 * 生成安全的随机密钥
 * @param length 密钥长度
 * @returns 随机密钥
 */
export function generateSecureKey(length: number = 32): string {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?'
  const crypto = window.crypto || (window as any).msCrypto

  if (crypto && crypto.getRandomValues) {
    // 使用Web Crypto API生成更安全的随机数
    const array = new Uint32Array(length)
    crypto.getRandomValues(array)
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars[array[i] % chars.length]
    }
    return result
  } else {
    // 回退方案
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  }
}

export default {
  enhancedEncrypt,
  enhancedDecrypt,
  encryptSensitiveData,
  decryptLoginData,
  validateEncryptedData,
  generateSecureKey
}