package org.example.Utils;


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

/**
 * AES对称加密
 */
public class AESUtil {
    private static final String KEY = "12345678901234567890123456789012";
    private static final String MOB_KEY = "lserpasebygyc222";
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; // Java中PKCS7Padding对应PKCS5Padding

    public static String encrypt(String toEncrypt) {
        return encrypt(toEncrypt, KEY);
    }

    public static String mobileEncrypt(String toEncrypt) {
        return encrypt(toEncrypt, MOB_KEY);
    }

    public static String decrypt(String toDecrypt) {
        return decrypt(toDecrypt, KEY);
    }

    public static String mobileDecrypt(String toDecrypt) {
        return decrypt(toDecrypt, MOB_KEY);
    }

    /**
     * AES加密（加密步骤）
     * 1，加密字符串得到二进制数组；
     * 2，将二进制数组转为16进制；
     * 3，进行base64编码
     *
     * @param toEncrypt 要加密的字符串
     * @param key       密钥
     * @return 加密后的字符串
     */
    public static String encrypt(String toEncrypt, String key) {
        if (toEncrypt == null || toEncrypt.isEmpty()) {
            return "";
        }
        try {
            // 密钥字节数组（ASCII编码，与C#保持一致）
            byte[] keyBytes = key.getBytes(StandardCharsets.US_ASCII);
            // 待加密内容字节数组（UTF-8编码）
            byte[] sourceBytes = toEncrypt.getBytes(StandardCharsets.UTF_8);

            // 初始化AES加密器
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            // 执行加密
            byte[] cryptData = cipher.doFinal(sourceBytes);

            // 二进制转16进制字符串
            String hexCryptString = hex2To16(cryptData);

            // 16进制字符串转字节数组后进行Base64编码
            byte[] hexBytes = hexCryptString.getBytes(StandardCharsets.UTF_8);
            return Base64.getEncoder().encodeToString(hexBytes);

        } catch (Exception e) {
            throw new RuntimeException("AES加密失败", e);
        }
    }

    /**
     * AES解密（解密步骤）
     * 1，将BASE64字符串转为16进制数组
     * 2，将16进制数组转为字符串
     * 3，将字符串转为二进制数据
     * 4，用AES解密数据
     *
     * @param toDecrypt 已加密的内容
     * @param key       密钥
     * @return 解密后的字符串
     */
    public static String decrypt(String toDecrypt, String key) {
        if (toDecrypt == null || toDecrypt.isEmpty()) {
            return "";
        }
        try {
            // 密钥字节数组（ASCII编码）
            byte[] keyBytes = key.getBytes(StandardCharsets.US_ASCII);

            // 初始化AES解密器
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            // Base64解码得到16进制字符串字节数组
            byte[] encryptedData = Base64.getDecoder().decode(toDecrypt);
            // 转为16进制字符串
            String encryptedString = new String(encryptedData, StandardCharsets.UTF_8);
            // 16进制字符串转二进制数组
            byte[] sourceBytes = hex16To2(encryptedString);

            // 执行解密
            byte[] originalData = cipher.doFinal(sourceBytes);

            // 解密后的数据转UTF-8字符串
            return new String(originalData, StandardCharsets.UTF_8);

        } catch (Exception e) {
            throw new RuntimeException("AES解密失败", e);
        }
    }

    /**
     * 二进制转16进制字符串
     *
     * @param bytes 二进制数组
     * @return 16进制字符串
     */
    private static String hex2To16(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        int maxLength = Math.min(65535, bytes.length); // 与C#保持一致的长度限制
        for (int i = 0; i < maxLength; i++) {
            // 格式化为两位大写十六进制，与C#的ToString("X2")保持一致
            sb.append(String.format("%02X", bytes[i]));
        }
        return sb.toString();
    }

    /**
     * 16进制字符串转二进制数组
     *
     * @param hexString 16进制字符串
     * @return 二进制数组
     */
    private static byte[] hex16To2(String hexString) {
        if (hexString == null || hexString.isEmpty()) {
            return new byte[0];
        }
        // 处理长度为奇数的情况，与C#保持一致
        if (hexString.length() % 2 != 0) {
            hexString += " ";
        }
        hexString = hexString.replace(" ", ""); // 移除空格
        int length = hexString.length() / 2;
        byte[] result = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            // 截取两位16进制字符并转换为字节
            result[i] = (byte) Integer.parseInt(hexString.substring(pos, pos + 2), 16);
        }
        return result;
    }
}