package com.red.circle.other.infra.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

public class AesUtils {
    private static final Base64.Encoder base64Encoder = Base64.getUrlEncoder();
    private static final Base64.Decoder base64Decoder = Base64.getUrlDecoder();
    private static final int IV_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16; // GCM tag length in bytes

    public static String generateAESKey() throws Exception {
        final int keyLength = 32; // 256-bit key (AES-256)
        final String charSet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        final int charSetLength = charSet.length();

        SecureRandom random = new SecureRandom();
        StringBuilder keyBuilder = new StringBuilder(keyLength);
        for (int i = 0; i < keyLength; i++) {
            int index = random.nextInt(charSetLength);
            keyBuilder.append(charSet.charAt(index));
        }

        return keyBuilder.toString();
    }

    // 验证并转换字符串密钥为字节数组
    private static SecretKeySpec validateKey(String key) throws Exception {
        int keyLength = key.length();
        if (keyLength != 16 && keyLength != 24 && keyLength != 32) {
            throw new IllegalArgumentException("Invalid AES key size (must be 16, 24, or 32 bytes)");
        }
        return new SecretKeySpec(key.getBytes(), "AES");
    }

    // 使用AES加密并返回Base64编码结果
    public static String encryptAESWithBase64(byte[] data, String key) throws Exception {
        // 验证并转换密钥
        SecretKeySpec keyBytes = validateKey(key);

        // 创建AES加密块
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // 生成随机IV（Nonce），长度为GCM推荐的NonceSize
        byte[] iv = new byte[IV_LENGTH];
        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);

        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);

        // 初始化加密器
        cipher.init(Cipher.ENCRYPT_MODE, keyBytes, gcmParameterSpec);

        // 加密数据
        byte[] ciphertext = cipher.doFinal(data);

        // 拼接IV和密文
        byte[] finalData = new byte[iv.length + ciphertext.length];
        System.arraycopy(iv, 0, finalData, 0, iv.length);
        System.arraycopy(ciphertext, 0, finalData, iv.length, ciphertext.length);

        // 返回Base64编码字符串
        return base64Encoder.encodeToString(finalData);
    }

    // 使用AES解密Base64编码数据
    public static String decryptAESWithBase64(String base64Data, String key) throws Exception {
        System.out.println("解码原数据:"+ base64Data);
        // 验证并转换密钥
        SecretKeySpec keyBytes = validateKey(key);

        // 解码Base64字符串
        byte[] encryptedData = base64Decoder.decode(base64Data);

        // 创建AES加密块
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");

        // 检查数据长度是否足够（至少包含一个Nonce）
        if (encryptedData.length < GCM_TAG_LENGTH) {
            throw new IllegalArgumentException("Encrypted data too short");
        }

        // 提取IV和密文
        byte[] iv = new byte[IV_LENGTH];
        System.arraycopy(encryptedData, 0, iv, 0, iv.length);
        byte[] ciphertext = new byte[encryptedData.length - iv.length];
        System.arraycopy(encryptedData, iv.length, ciphertext, 0, ciphertext.length);

        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv);

        // 初始化解密器
        cipher.init(Cipher.DECRYPT_MODE, keyBytes, gcmParameterSpec);

        // 解密数据
        String decryptStr = new String(cipher.doFinal(ciphertext));
        System.out.println("解密后数据:"+ decryptStr);
        return decryptStr;
    }

    public static void main(String[] args) {
        try {
            // 生成AES密钥
            String key = "Lt2tYDHewn6U44GaBiU0YirfmeJtA6Jr";

            String base64Str = "{\n" +
                    "    \"game_id\": \"123\",\n" +
                    "    \"user_id\": \"1957345312961527809\",\n" +
                    "    \"token\": \"4C5BE79533FACBE3ADFEB22D60CFA771.djIlM0ExOTU3MzQ1MzEyOTYxNTI3ODA5JTNBTElLRUklM0ExNzcxNDIyNTgyNTY1JTNBMTc2ODgzMDU4MjU2NQ==\",\n" +
                    "    \"change_value\": 100,\n" +
                    "    \"change_cause\": \"bet\",\n" +
                    "    \"change_time\": 23423,\n" +
                    "    \"room_id\": \"1111\",\n" +
                    "    \"record_id\": \"recordId\",\n" +
                    "    \"round_id\": \"roundIdddd\"\n" +
                    "}";

            String encryptedData2 = encryptAESWithBase64(base64Str.getBytes(), key);
            System.out.println("Encrypt Data: " + encryptedData2);

            // 解密2
            String decryptedData2 = decryptAESWithBase64(encryptedData2, key);
            System.out.println("Decrypted Data2: " + decryptedData2);

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