import 'dart:convert';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:encrypt/encrypt.dart' as encrypt;

/// AES加密解密工具
class AESUtils {
// Encrypt function: Takes plaintext and key, returns base64 ciphertext and nonce
  Map<String, String> encryptData(String plainText, String keyStr) {
    // Generate timestamp as nonce
    String nonce = DateTime.now().toIso8601String();

    // Generate key and IV
    final key = generateKey(keyStr);
    final iv = generateIv(nonce, keyStr);

    // Encrypt the data
    final encrypter = encrypt.Encrypter(
        encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: 'PKCS7'));
    final encrypted = encrypter.encrypt(plainText, iv: iv);

    return {
      'data': encrypted.base64,
      'time': nonce,
    };
  }

// Decrypt function: Takes base64 ciphertext, key, and nonce, returns plaintext
  String decryptData(String cipherText, String keyStr, String nonce) {
    // Generate key and IV
    final key = generateKey(keyStr);
    final iv = generateIv(nonce, keyStr);

    // Decrypt the data
    final encrypter = encrypt.Encrypter(
        encrypt.AES(key, mode: encrypt.AESMode.cbc, padding: 'PKCS7'));
    final decrypted = encrypter.decrypt64(cipherText, iv: iv);

    return decrypted;
  }

// Generate AES key from input key (32 bytes for AES-256)
  encrypt.Key generateKey(String keyStr) {
    final keyBytes = sha256.convert(utf8.encode(keyStr)).bytes;
    return encrypt.Key(Uint8List.fromList(keyBytes));
  }

// Generate IV (Initialization Vector) from nonce and key
  encrypt.IV generateIv(String ivStr, String keyStr) {
    final md5Hash = md5.convert(utf8.encode(ivStr)).bytes;
    final combinedKey = hexEncode(md5Hash) + keyStr;
    final finalHash = sha256.convert(utf8.encode(combinedKey)).bytes;

    return encrypt.IV(Uint8List.fromList(
        finalHash.sublist(0, 16))); // AES-CBC IV must be 16 bytes
  }

// Helper function to encode bytes to hex
  String hexEncode(List<int> bytes) {
    return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join('');
  }
}
