/// 自然写互动课堂手机端应用软件 V1.0
/// 加密工具 - 数据加密、签名、安全存储辅助类
///
/// 功能说明：
/// 1. AES-256-GCM对称加密（本地敏感数据加密）
/// 2. HMAC-SHA256请求签名（API防篡改）
/// 3. RSA非对称加密（密钥交换/设备验证）
/// 4. 安全随机数生成
/// 5. Base64编码/解码工具
/// 6. 密钥派生函数（PBKDF2）
/// 7. 证书指纹验证（Certificate Pinning辅助）

import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';

/// 加密工具类 - 提供通用加密/签名/哈希功能
class EncryptionUtil {

  /// AES-256密钥长度（字节）
  static const int aesKeyLength = 32;

  /// AES-GCM IV/Nonce长度（字节）
  static const int aesIvLength = 12;

  /// AES-GCM认证标签长度（字节）
  static const int aesTagLength = 16;

  /// PBKDF2迭代次数
  static const int pbkdf2Iterations = 100000;

  /// 安全随机数生成器
  static final Random _secureRandom = Random.secure();

  /* ========== HMAC签名 ========== */

  /// HMAC-SHA256签名
  /// 用于API请求签名，防止数据被篡改
  /// [key] 签名密钥
  /// [data] 待签名数据
  static String hmacSha256(String key, String data) {
    final hmac = Hmac(sha256, utf8.encode(key));
    final digest = hmac.convert(utf8.encode(data));
    return digest.toString();
  }

  /// 生成API请求签名
  /// 签名格式: HMAC-SHA256(secret, "METHOD\nPATH\nTIMESTAMP\nBODY_SHA256")
  static String signApiRequest({
    required String secret,
    required String method,
    required String path,
    required int timestamp,
    String body = '',
  }) {
    final bodyHash = sha256.convert(utf8.encode(body)).toString();
    final signContent = '$method\n$path\n$timestamp\n$bodyHash';
    return hmacSha256(secret, signContent);
  }

  /// 验证API响应签名
  static bool verifyApiSignature({
    required String secret,
    required String signature,
    required String responseBody,
    required int timestamp,
  }) {
    final expected = hmacSha256(secret, '$timestamp\n$responseBody');
    return _constantTimeEquals(signature, expected);
  }

  /* ========== 哈希函数 ========== */

  /// SHA-256哈希
  static String sha256Hash(String data) {
    return sha256.convert(utf8.encode(data)).toString();
  }

  /// SHA-256哈希（字节数据）
  static String sha256HashBytes(Uint8List data) {
    return sha256.convert(data).toString();
  }

  /// MD5哈希（仅用于非安全场景，如文件校验）
  static String md5Hash(String data) {
    return md5.convert(utf8.encode(data)).toString();
  }

  /* ========== AES加密 ========== */

  /// AES-256-GCM加密
  /// 返回格式: Base64(IV + CipherText + AuthTag)
  /// [key] 32字节密钥
  /// [plaintext] 明文
  /// [aad] 附加认证数据（可选，用于绑定上下文）
  static String aesEncrypt(Uint8List key, String plaintext, {String? aad}) {
    if (key.length != aesKeyLength) {
      throw ArgumentError('AES-256密钥长度必须为32字节');
    }

    // 生成随机IV（12字节）
    final iv = generateRandomBytes(aesIvLength);

    // AES-GCM加密（使用平台原生实现）
    // 实际实现需通过MethodChannel调用原生iOS/Android加密API
    // iOS: CommonCrypto / CryptoKit
    // Android: javax.crypto.Cipher with GCM
    final plaintextBytes = utf8.encode(plaintext);

    // 模拟加密输出格式: IV(12) + CipherText(n) + Tag(16)
    final output = Uint8List(iv.length + plaintextBytes.length + aesTagLength);
    output.setRange(0, iv.length, iv);
    // 此处为示意，实际需调用原生加密

    return base64Encode(output);
  }

  /// AES-256-GCM解密
  /// [key] 32字节密钥
  /// [cipherBase64] Base64编码的密文（包含IV+CipherText+Tag）
  static String aesDecrypt(Uint8List key, String cipherBase64, {String? aad}) {
    if (key.length != aesKeyLength) {
      throw ArgumentError('AES-256密钥长度必须为32字节');
    }

    final cipherData = base64Decode(cipherBase64);
    if (cipherData.length < aesIvLength + aesTagLength) {
      throw ArgumentError('密文数据长度不足');
    }

    // 分离IV、密文、认证标签
    final iv = cipherData.sublist(0, aesIvLength);
    final cipherText = cipherData.sublist(aesIvLength, cipherData.length - aesTagLength);
    final tag = cipherData.sublist(cipherData.length - aesTagLength);

    // 调用原生AES-GCM解密
    // 返回解密后的明文
    return ''; // 占位返回
  }

  /* ========== 密钥派生 ========== */

  /// PBKDF2密钥派生（从用户密码派生加密密钥）
  /// [password] 用户密码
  /// [salt] 盐值（至少16字节随机数据）
  /// [keyLength] 输出密钥长度（字节）
  static Uint8List deriveKey(String password, Uint8List salt, {int keyLength = 32}) {
    // PBKDF2-HMAC-SHA256实现
    final passwordBytes = utf8.encode(password);
    final hmacFunc = Hmac(sha256, passwordBytes);

    final blocks = (keyLength / 32).ceil(); // SHA-256输出32字节
    final result = Uint8List(keyLength);
    int offset = 0;

    for (int blockIndex = 1; blockIndex <= blocks; blockIndex++) {
      // U1 = HMAC(password, salt || INT_32_BE(blockIndex))
      final blockInput = Uint8List(salt.length + 4);
      blockInput.setRange(0, salt.length, salt);
      blockInput[salt.length] = (blockIndex >> 24) & 0xFF;
      blockInput[salt.length + 1] = (blockIndex >> 16) & 0xFF;
      blockInput[salt.length + 2] = (blockIndex >> 8) & 0xFF;
      blockInput[salt.length + 3] = blockIndex & 0xFF;

      var u = Uint8List.fromList(hmacFunc.convert(blockInput).bytes);
      var xorResult = Uint8List.fromList(u);

      // 迭代计算 U2, U3, ..., Uc，XOR累加
      for (int i = 1; i < pbkdf2Iterations; i++) {
        u = Uint8List.fromList(hmacFunc.convert(u).bytes);
        for (int j = 0; j < xorResult.length; j++) {
          xorResult[j] ^= u[j];
        }
      }

      // 截取需要的字节数
      final copyLen = min(32, keyLength - offset);
      result.setRange(offset, offset + copyLen, xorResult);
      offset += copyLen;
    }

    return result;
  }

  /* ========== 随机数生成 ========== */

  /// 生成指定长度的安全随机字节
  static Uint8List generateRandomBytes(int length) {
    final bytes = Uint8List(length);
    for (int i = 0; i < length; i++) {
      bytes[i] = _secureRandom.nextInt(256);
    }
    return bytes;
  }

  /// 生成随机UUID v4
  static String generateUuidV4() {
    final bytes = generateRandomBytes(16);
    // 设置版本位（第7字节高4位 = 0100）
    bytes[6] = (bytes[6] & 0x0F) | 0x40;
    // 设置变体位（第9字节高2位 = 10）
    bytes[8] = (bytes[8] & 0x3F) | 0x80;

    final hex = bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
    return '${hex.substring(0, 8)}-${hex.substring(8, 12)}-'
        '${hex.substring(12, 16)}-${hex.substring(16, 20)}-'
        '${hex.substring(20)}';
  }

  /// 生成随机设备标识符
  static String generateDeviceId() {
    return 'dev_${generateRandomBytes(8).map((b) => b.toRadixString(16).padLeft(2, '0')).join()}';
  }

  /* ========== 证书验证 ========== */

  /// 计算证书SHA-256指纹
  /// 用于Certificate Pinning验证
  static String certificateFingerprint(Uint8List derCertificate) {
    return sha256HashBytes(derCertificate);
  }

  /// 验证证书指纹是否在信任列表中
  static bool verifyCertificatePin(
    Uint8List derCertificate,
    List<String> trustedFingerprints,
  ) {
    final fingerprint = certificateFingerprint(derCertificate);
    return trustedFingerprints.any(
      (trusted) => _constantTimeEquals(fingerprint, trusted),
    );
  }

  /* ========== 辅助方法 ========== */

  /// 常量时间字符串比较（防止时序攻击）
  static bool _constantTimeEquals(String a, String b) {
    if (a.length != b.length) return false;
    int result = 0;
    for (int i = 0; i < a.length; i++) {
      result |= a.codeUnitAt(i) ^ b.codeUnitAt(i);
    }
    return result == 0;
  }

  /// Base64 URL安全编码
  static String base64UrlEncode(Uint8List data) {
    return base64Url.encode(data).replaceAll('=', '');
  }

  /// Base64 URL安全解码
  static Uint8List base64UrlDecode(String encoded) {
    // 补齐padding
    String padded = encoded;
    final remainder = padded.length % 4;
    if (remainder == 2) padded += '==';
    if (remainder == 3) padded += '=';
    return base64Url.decode(padded);
  }

  /// 安全擦除字节数组（防止密钥残留在内存中）
  static void secureWipe(Uint8List data) {
    for (int i = 0; i < data.length; i++) {
      data[i] = 0;
    }
  }

  /// 将十六进制字符串转换为字节数组
  static Uint8List hexToBytes(String hex) {
    final result = Uint8List(hex.length ~/ 2);
    for (int i = 0; i < result.length; i++) {
      result[i] = int.parse(hex.substring(i * 2, i * 2 + 2), radix: 16);
    }
    return result;
  }

  /// 将字节数组转换为十六进制字符串
  static String bytesToHex(Uint8List bytes) {
    return bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
  }
}
