package com.example.sjkbf.util;

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

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class RSATooL {


    private static String prkey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANp/KnuAZq609lnc\n" +
            "jciVgt/xDLDEaKC+DSuSZc9o/fgLqweL/8Yu5iPAzoBQlO1t+jSkI2YuoFsKKK7O\n" +
            "QFcSoz4Z5Lb7vOG7XJ4Re/6L2LJIU9tjJ3LznW5WKnuiqxs0ziIZilLkRE0P1di6\n" +
            "FIZQUjmn2KQ2y/P7PuviJPat3y+vAgMBAAECgYEAmn64h0MvV/FVEA1Ho8E0HSzQ\n" +
            "kF0Qrjg0D88gdhwDGFUHxfpUDMo0qKs4WLqh05CkDnzRGvt1H2p7gb8M94SSL5SX\n" +
            "mCR2ZLiCQJy5tZpQNRUt9P67upLcDcKJ6YPujcuEdlo0pzKGGMZk8Uvh05S9lnwl\n" +
            "yWJeEk4G7q5Aalz8vIECQQDwBVJH60Gd2St/GS4dCtXwHTO9HJZRaWEkaXPgVbXI\n" +
            "vqv+jtD4HpzDCpgv/kUK0fnb4V/9/LM1SHOedVMfmh0fAkEA6QsChdHiU1lHfL1b\n" +
            "Z3Uvxvi/Zk8i0ryzBaYudrzNmb7iJcssJPPty3KTjihgvw2W36GV+2GlQBEjOf2B\n" +
            "2WgLcQJBAO66XDxsIbd+aWThBpycSm2one1aoagXyCcPO9HFbilcfHWUVwRybjkQ\n" +
            "MI6LuOAqOPoaD//vd89nYJga2bJ09sECQFmXRPoDTVozqXr4JSqp75szyAliBQY1\n" +
            "SzGxyI0XWodvzesvp6HxMQsU2ks9lKv+YnFI4qsIyAnQTNWfcwsMp9ECQDba0LJV\n" +
            "xI0SIznsVtBb7T5Ir9ppLKx1QTNcytkjHxmQqWGy+57ojjQ6GV3z4fSwNGjIhsOT\n" +
            "DFgz0gEcRr13bRk=";
    private static String pubkey =
            "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDafyp7gGautPZZ3I3IlYLf8Qyw\n" +
            "xGigvg0rkmXPaP34C6sHi//GLuYjwM6AUJTtbfo0pCNmLqBbCiiuzkBXEqM+GeS2\n" +
            "+7zhu1yeEXv+i9iySFPbYydy851uVip7oqsbNM4iGYpS5ERND9XYuhSGUFI5p9ik\n" +
            "Nsvz+z7r4iT2rd8vrwIDAQAB";
    static RSA rsa2 = new RSA(prkey, pubkey);

    /**
     * 解密
     * @param str
     * @return
     */
    public static String  decrypt(String str){

        str= str.replaceAll(" ","+");
        byte[] decrypt2 = rsa2.decrypt(str, KeyType.PrivateKey);
        String s = new String(decrypt2);
        String[] split = s.split("");
        s = split[0];
        return s;
    }

    /**
     * 加密
     * @param str
     * @return
     */
    public static String  encryption(String str){
        return Base64.encode(rsa2.encrypt(str, KeyType.PrivateKey));
    }



    /**
     * 使用RSA公钥解密
     * @param encryptedData 加密后的数据（Base64编码）
     * @return 解密后的原始字符串
     */
    public static String decryptByPublicKey( String encryptedData) {


        // 解密步骤：
        // 1. 将Base64编码的加密数据解码为字节数组
        // 2. 使用公钥解密（指定KeyType.PublicKey）
        // 3. 将解密后的字节数组转换为字符串
        byte[] decryptedBytes = rsa2.decrypt(Base64.decode(encryptedData), KeyType.PublicKey);

        return new String(decryptedBytes, StandardCharsets.UTF_8);
    }


    public static void main(String[] args) {
        System.out.println(decompress("H4sIAAAAAAAAAKtWyk6tVLJSUggKdgzJz/fRS81LLqosKMnMz9MAyhTrleQHlxRl5qVraCrVAgAXNYHCLQAAAA=="));
    }

    //异或加密
    public static byte[] Makecode(byte[] pstr,int[] Key) {
        byte[] Str = pstr;

        for (int i = 0; i < Str.length; i++) {
            byte sbuf = Str[i];
            Str[i] = MakecodeChar(sbuf, Key[i % 20], Key[(i + 18) % 20]);
        }

        return Str;
    }

    //字符串异或
    public static String encryptDecrypt(String input, String key) {
        StringBuilder output = new StringBuilder(input);
        int keyLength = key.length();

        for (int i = 0; i < input.length(); i++) {
            // 对每个字符进行异或运算
            output.setCharAt(i, (char) (input.charAt(i) ^ key.charAt(i % keyLength)));
        }

        return output.toString();
    }


    //单个字符加密
    public static byte MakecodeChar(byte c, int key, int key2) {
        return (byte) ((((c + key) ^ key2) ^ key) + 1);
    }


    /**
     * 单个字符解密，对应C++的CutcodeChar
     * @param c 待解密的字符（Java中用byte表示，对应C++的char）
     * @param key 第一个密钥
     * @param key2 第二个密钥
     * @return 解密后的字符（byte）
     */
    public static byte cutcodeChar(byte c, int key, int key2) {
        // 对应C++的：(((c - 1) ^ key) ^ key2) - key
        // 注意：Java中byte是8位有符号数，运算时会自动提升为int，最后强转为byte
        int step1 = (c - 1) ^ key;
        int step2 = step1 ^ key2;
        int result = step2 - key;
        return (byte) result;
    }

    /**
     * 字节数组解密，对应C++的Cutecode
     * @param pstr 待解密的字节数组（对应C++的char*）
     * @param pkey 密钥数组
     * @param len 待解密的长度（-1表示使用整个数组长度）
     * @param keyLength 密钥长度（默认5，与C++默认参数一致）
     * @return 解密后的字节数组（原数组会被修改，同时返回新数组方便链式调用）
     */
    public static byte[] cutecode(byte[] pstr, int[] pkey, int len, int keyLength) {
        // 处理默认长度：如果len为-1，则使用数组的实际长度
        if (len == -1) {
            len = pstr.length;
        }
        // 遍历每个字节进行解密
        for (int i = 0; i < len; i++) {
            // 计算密钥索引，与C++逻辑一致
            int keyIndex = i % keyLength;
            int key2Index = (i + 18) % keyLength;
            // 调用单个字符解密方法，修改原数组
            pstr[i] = cutcodeChar(pstr[i], pkey[keyIndex], pkey[key2Index]);
        }
        return pstr;
    }

    // 重载方法：提供默认参数（对应C++的默认参数int keyLength = 5）
    public static byte[] cutecode(byte[] pstr, int[] pkey, int len) {
        return cutecode(pstr, pkey, len, 5);
    }

    // 重载方法：最简化调用（len=-1，keyLength=5）
    public static byte[] cutecode(byte[] pstr, int[] pkey) {
        return cutecode(pstr, pkey, -1, 5);
    }
    /**
     * 压缩字符串
     * @param input 原始字符串
     * @return Base64编码后的压缩字符串（便于存储/传输）
     */
    public static String compress(String input) {
        if (input == null || input.isEmpty()) {
            return input;
        }

        try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
            GZIPOutputStream gzipOS = new GZIPOutputStream(bos)) {

            gzipOS.write(input.getBytes(StandardCharsets.UTF_8));
            gzipOS.finish();

            // 将压缩后的字节数组转为Base64字符串（避免二进制乱码）
            byte[] compressedBytes = bos.toByteArray();
            return java.util.Base64.getEncoder().encodeToString(compressedBytes);

        } catch (IOException e) {
            throw new RuntimeException("压缩失败", e);
        }
    }


    /**
     * 解压字符串
     * @param compressedStr Base64编码后的压缩字符串
     * @return 解压后的原始字符串
     */
    public static String decompress(String compressedStr) {
        if (compressedStr == null || compressedStr.isEmpty()) {
            return compressedStr;
        }

        byte[] compressedBytes = java.util.Base64.getDecoder().decode(compressedStr);
        System.out.println(Arrays.toString(compressedBytes));
        try (ByteArrayInputStream bis = new ByteArrayInputStream(compressedBytes);
             GZIPInputStream gzipIS = new GZIPInputStream(bis);
             ByteArrayOutputStream bos = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[1024];
            int len;
            while ((len = gzipIS.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }

            return new String(bos.toByteArray(), StandardCharsets.UTF_8);

        } catch (IOException e) {
            throw new RuntimeException("解压失败", e);
        }
    }

}
