/**
 * 加密解密工具模块
 * 支持AES-CBC加密解密，可配置密钥和IV
 * 采用解耦设计，便于扩展和关闭
 */

import CryptoJS from 'crypto-js';

/**
 * 加密配置接口
 */
export interface CryptoConfig {
  key: string;
  iv: string;
  mode?: typeof CryptoJS.mode.CBC;
  padding?: typeof CryptoJS.pad.Pkcs7;
}

/**
 * 默认加密配置
 */
export const DEFAULT_CRYPTO_CONFIG: CryptoConfig = {
  key: 'k0f3JfxEWd3HC7pXQU8tmSkDheUXibmz',
  iv: 'Fu2wU73MBcsEZWJk',
  mode: CryptoJS.mode.CBC,
  padding: CryptoJS.pad.Pkcs7
};

/**
 * 加密解密工具类
 */
export class CryptoUtils {
  private config: CryptoConfig;
  private enabled: boolean;

  constructor(config?: CryptoConfig, enabled: boolean = true) {
    this.config = config || DEFAULT_CRYPTO_CONFIG;
    this.enabled = enabled;
  }

  /**
   * 设置加密配置
   */
  setConfig(config: CryptoConfig): void {
    this.config = config;
  }

  /**
   * 启用/禁用加密功能
   */
  setEnabled(enabled: boolean): void {
    this.enabled = enabled;
  }

  /**
   * 加密数据
   */
  encrypt(data: string): string {
    if (!this.enabled) {
      return data;
    }

    try {
      const encrypted = CryptoJS.AES.encrypt(data, CryptoJS.enc.Utf8.parse(this.config.key), {
        iv: CryptoJS.enc.Utf8.parse(this.config.iv),
        mode: this.config.mode || CryptoJS.mode.CBC,
        padding: this.config.padding || CryptoJS.pad.Pkcs7
      });
      
      return encrypted.toString();
    } catch (error) {
      console.error('加密失败:', error);
      throw new Error('数据加密失败');
    }
  }

  /**
   * 解密数据
   */
  decrypt(encryptedData: string): string {
    if (!this.enabled) {
      return encryptedData;
    }

    try {
      const decrypted = CryptoJS.AES.decrypt(encryptedData, CryptoJS.enc.Utf8.parse(this.config.key), {
        iv: CryptoJS.enc.Utf8.parse(this.config.iv),
        mode: this.config.mode || CryptoJS.mode.CBC,
        padding: this.config.padding || CryptoJS.pad.Pkcs7
      });
      
      return decrypted.toString(CryptoJS.enc.Utf8);
    } catch (error) {
      console.error('解密失败:', error);
      throw new Error('数据解密失败');
    }
  }

  /**
   * 加密对象（转换为JSON后加密）
   */
  encryptObject(obj: any): string {
    const jsonString = JSON.stringify(obj);
    return this.encrypt(jsonString);
  }

  /**
   * 解密对象
   */
  decryptObject(encryptedData: string): any {
    const jsonString = this.decrypt(encryptedData);
    return JSON.parse(jsonString);
  }

  /**
   * 验证加密功能是否可用
   */
  isAvailable(): boolean {
    return this.enabled && !!this.config.key && !!this.config.iv;
  }
}

/**
 * 默认加密工具实例
 */
export const defaultCrypto = new CryptoUtils();

/**
 * 创建加密工具实例
 */
export const createCrypto = (config?: CryptoConfig, enabled?: boolean): CryptoUtils => {
  return new CryptoUtils(config, enabled);
};

export default CryptoUtils;