package top.continew.admin.common.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;

import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;

/**
 * RSA加密测试工具类
 * 独立运行，不依赖Spring容器
 *
 * @author Charles7c
 * @since 2024/12/04 16:30
 */
public class RsaTestUtil {

    // 项目中使用的RSA密钥对
    private static final String PUBLIC_KEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAM51dgYtMyF+tTQt80sfFOpSV27a7t9uaUVeFrdGiVxscuizE7H8SMntYqfn9lp8a5GH5P1/GGehVjUD2gF/4kcCAwEAAQ==";
    private static final String PRIVATE_KEY = "MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAznV2Bi0zIX61NC3zSx8U6lJXbtru325pRV4Wt0aJXGxy6LMTsfxIye1ip+f2WnxrkYfk/X8YZ6FWNQPaAX/iRwIDAQABAkEAk/VcAusrpIqA5Ac2P5Tj0VX3cOuXmyouaVcXonr7f+6y2YTjLQuAnkcfKKocQI/juIRQBFQIqqW/m1nmz1wGeQIhAO8XaA/KxzOIgU0l/4lm0A2Wne6RokJ9HLs1YpOzIUmVAiEA3Q9DQrpAlIuiT1yWAGSxA9RxcjUM/1kdVLTkv0avXWsCIE0X8woEjK7lOSwzMG6RpEx9YHdopjViOj1zPVH61KTxAiBmv/dlhqkJ4rV46fIXELZur0pj6WC3N7a4brR8a+CLLQIhAMQyerWl2cPNVtE/8tkziHKbwW3ZUiBXU24wFxedT9iV";

    /**
     * RSA公钥加密
     *
     * @param data      要加密的内容
     * @param publicKey 公钥
     * @return 加密后的内容（Base64编码）
     */
    public static String encrypt(String data, String publicKey) {
        return Base64.encode(SecureUtil.rsa(null, publicKey).encrypt(data.getBytes(), KeyType.PublicKey));
    }

    /**
     * RSA私钥解密
     *
     * @param data       要解密的内容（Base64编码）
     * @param privateKey 私钥
     * @return 解密后的内容
     */
    public static String decrypt(String data, String privateKey) {
        return new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(data), KeyType.PrivateKey));
    }

    /**
     * 使用项目默认密钥加密
     *
     * @param data 要加密的内容
     * @return 加密后的内容
     */
    public static String encryptWithDefaultKey(String data) {
        return encrypt(data, PUBLIC_KEY);
    }

    /**
     * 使用项目默认密钥解密
     *
     * @param data 要解密的内容
     * @return 解密后的内容
     */
    public static String decryptWithDefaultKey(String data) {
        return decrypt(data, PRIVATE_KEY);
    }

    /**
     * 生成新的RSA密钥对
     *
     * @return 密钥对数组 [公钥, 私钥]
     */
    public static String[] generateKeyPair() {
        try {
            KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
            keyGen.initialize(1024); // 可以改为2048获得更高安全性
            KeyPair pair = keyGen.generateKeyPair();

            String publicKey = Base64.encode(pair.getPublic().getEncoded());
            String privateKey = Base64.encode(pair.getPrivate().getEncoded());

            return new String[] {publicKey, privateKey};
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("生成RSA密钥对失败", e);
        }
    }

    /**
     * 测试RSA加密解密功能
     */
    public static void testRsaEncryption() {
        System.out.println("=== RSA加密解密测试 ===");

        String[] testData = {"Test123456", "Admin@2024", "MyPassword123!", "简单密码123", "Special!@#$%^&*()Chars", ""  // 空字符串测试
        };

        for (String data : testData) {
            try {
                System.out.println("\n测试数据: \"" + data + "\"");

                // 加密
                String encrypted = encryptWithDefaultKey(data);
                System.out.println("加密结果: " + encrypted);

                // 解密
                String decrypted = decryptWithDefaultKey(encrypted);
                System.out.println("解密结果: \"" + decrypted + "\"");

                // 验证
                if (data.equals(decrypted)) {
                    System.out.println("✓ 测试通过");
                } else {
                    System.out.println("✗ 测试失败 - 原始数据与解密结果不匹配");
                }

            } catch (Exception e) {
                System.out.println("✗ 测试失败 - " + e.getMessage());
            }
        }
    }

    /**
     * 测试密钥生成功能
     */
    public static void testKeyGeneration() {
        System.out.println("\n=== RSA密钥生成测试 ===");

        try {
            String[] keyPair = generateKeyPair();
            String publicKey = keyPair[0];
            String privateKey = keyPair[1];

            System.out.println("生成的公钥: " + publicKey);
            System.out.println("生成的私钥: " + privateKey);

            // 使用新生成的密钥测试加密解密
            String testData = "TestWithNewKeys123";
            String encrypted = encrypt(testData, publicKey);
            String decrypted = decrypt(encrypted, privateKey);

            System.out.println("\n使用新密钥测试:");
            System.out.println("原始数据: " + testData);
            System.out.println("加密结果: " + encrypted);
            System.out.println("解密结果: " + decrypted);

            if (testData.equals(decrypted)) {
                System.out.println("✓ 新密钥测试通过");
            } else {
                System.out.println("✗ 新密钥测试失败");
            }

        } catch (Exception e) {
            System.out.println("✗ 密钥生成测试失败 - " + e.getMessage());
        }
    }

    /**
     * 生成用于测试的加密密码
     *
     * @param passwords 要加密的密码数组
     */
    public static void generateEncryptedPasswords(String[] passwords) {
        System.out.println("\n=== 生成测试用加密密码 ===");

        for (String password : passwords) {
            try {
                String encrypted = encryptWithDefaultKey(password);
                System.out.println("原始密码: " + password);
                System.out.println("加密密码: " + encrypted);
                System.out.println("---");
            } catch (Exception e) {
                System.out.println("加密失败: " + password + " - " + e.getMessage());
            }
        }
    }

    /**
     * 主方法 - 运行所有测试
     */
    public static void main(String[] args) {
        try {
            // 基本加密解密测试
            testRsaEncryption();

            // 密钥生成测试
            testKeyGeneration();

            // 生成一些常用测试密码的加密版本
            String[] commonPasswords = {"Test123456", "Admin@2024", "Password123!", "SimplePass"};
            generateEncryptedPasswords(commonPasswords);

            System.out.println("\n=== 所有测试完成 ===");

        } catch (Exception e) {
            System.err.println("测试过程中发生错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
}
