package com.zsElectric.boot.common.util;

import com.esotericsoftware.minlog.Log;
import com.zsElectric.boot.common.constant.ConnectivityConstants;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

import static com.zsElectric.boot.common.constant.ConnectivityConstants.*;

/**
 * AES加解密工具类
 * 支持AES-128-CBC-PKCS5Padding对称加解密算法
 * @version 1.0
 */
@Slf4j
public class AESCryptoUtils {
    
    // 加密算法/模式/填充方式
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    private static final String AES = "AES";
    private static final int IV_SIZE = 16;   // 16字节

    /**
     * AES加密
     * @param data 待加密的明文
     * @param key 密钥（必须为16字节）
     * @param iv 初始化向量（必须为16字节）
     * @return Base64编码的加密结果
     * @throws Exception 加密异常
     */
    public static String encrypt(String data, String key, String iv) throws Exception {

        log.info("待加密数据：{}", data);

        // 参数校验
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("加密数据不能为空");
        }
        if (key == null || key.length() != 16) {
            throw new IllegalArgumentException("密钥必须为16位字符");
        }
        if (iv == null || iv.length() != IV_SIZE) {
            throw new IllegalArgumentException("初始化向量必须为16位字符");
        }

        try {
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES);
            // 创建初始化向量规范
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

            // 获取加密实例并初始化
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

            // 执行加密
            byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));

            // 返回Base64编码的加密结果
            return Base64.getEncoder().encodeToString(encryptedBytes);

        } catch (Exception e) {
            throw new Exception("AES加密失败: " + e.getMessage(), e);
        }
    }

    /**
     * AES解密
     * @param encryptedData Base64编码的加密数据
     * @param key 密钥（必须为16字节）
     * @param iv 初始化向量（必须为16字节）
     * @return 解密后的明文
     * @throws Exception 解密异常
     */
    public static String decrypt(String encryptedData, String key, String iv) throws Exception {
        // 参数校验
        if (encryptedData == null || encryptedData.isEmpty()) {
            throw new IllegalArgumentException("解密数据不能为空");
        }
        if (key == null || key.length() != 16) {
            throw new IllegalArgumentException("密钥必须为16位字符");
        }
        if (iv == null || iv.length() != 16) {
            throw new IllegalArgumentException("初始化向量必须为16位字符");
        }

        try {
            // 创建密钥规范
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), AES);
            // 创建初始化向量规范
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));

            // 获取解密实例并初始化
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

            // Base64解码并执行解密
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

            // 返回解密结果
            return new String(decryptedBytes, StandardCharsets.UTF_8);

        } catch (Exception e) {
            throw new Exception("AES解密失败: " + e.getMessage(), e);
        }
    }

    /**
     * 生成随机密钥（16字节）
     * @return 16字节的随机密钥
     */
    public static String generateRandomKey() {
        return generateRandomString(16);
    }

    /**
     * 生成随机初始化向量（16字节）
     * @return 16字节的随机IV
     */
    public static String generateRandomIV() {
        return generateRandomString(16);
    }

    /**
     * 生成指定长度的随机字符串
     * @param length 字符串长度
     * @return 随机字符串
     */
    private static String generateRandomString(int length) {
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            int index = (int) (characters.length() * Math.random());
            sb.append(characters.charAt(index));
        }
        return sb.toString();
    }
    
    /**
     * 测试方法
     */
    public static void main(String[] args) throws Exception {

        try {
            // 测试数据
            String originalData = "{\"OperatorID\":\"MA6DP6BE7\",\"SuccStat\":0,\"AccessToken\":\"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJNQTZEUDZCRTciLCJpYXQiOjE3NjQ1ODE0NzQsImV4cCI6MTc2NDU4ODY3NH0.mfXp_Wly4QiVYILK6hNSOEGSU7XejlYZRing0CRc8MQW1xuUxrQQwOxeCAwI_Bnay5WzqaYYFQeVuNeignxAuQ\",\"TokenAvailableTime\":6885,\"FailReason\":0}";
            String key = DATA_SECRET;   // 16字节密钥
            String iv = DATA_SECRET_IV;   // 16字节初始化向量

            System.out.println("=== AES-128-CBC-PKCS5Padding 加解密测试 ===");
            System.out.println("原始数据: " + originalData);
            System.out.println("密钥: " + key);
            System.out.println("初始化向量: " + iv);

            // 加密
            long startTime = System.currentTimeMillis();
            String encryptedData = encrypt(originalData, key, iv);
            long encryptTime = System.currentTimeMillis() - startTime;
            System.out.println("加密结果: " + encryptedData);
            System.out.println("加密耗时: " + encryptTime + "ms");

            String data = "KYWxoKWK3w8a8867aXCha+tgVE2cbZ4eR1Dc1YExri06DfZWBpUMAzlhY7rWR5SeU+xCVOauk4F7MxCJLN+5aJCBENCOAZtUksMM7VgsOz0=";
            System.out.println("测试的加密数据："+data);

            String key1 = DATA_SECRET;   // 16字节密钥
            String iv1 = DATA_SECRET_IV;
            System.out.println("密钥: " + key);
            System.out.println("初始化向量: " + iv);
            String string = decrypt(data, key1, iv1);
            System.out.println("测试的解密："+string);
            // 解密
            startTime = System.currentTimeMillis();
            String decryptedData = decrypt(encryptedData, key, iv);
            long decryptTime = System.currentTimeMillis() - startTime;
            System.out.println("解密结果: " + decryptedData);
            System.out.println("解密耗时: " + decryptTime + "ms");

            // 验证加解密一致性
            boolean isSuccess = originalData.equals(decryptedData);
            System.out.println("加解密验证: " + (isSuccess ? "成功" : "失败"));

            // 测试随机密钥生成
            System.out.println("\n=== 随机密钥生成测试 ===");
            String randomKey = generateRandomKey();
            String randomIV = generateRandomIV();
            System.out.println("随机密钥: " + randomKey);
            System.out.println("随机IV: " + randomIV);

            // 使用随机密钥进行加解密测试
            String testEncrypted = encrypt("测试数据", randomKey, randomIV);
            String testDecrypted = decrypt(testEncrypted, randomKey, randomIV);
            System.out.println("随机密钥加解密测试: " + ("测试数据".equals(testDecrypted) ? "成功" : "失败"));

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}