package com.gree.mall.manager.utils;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class EncryptUtils {

    static {
        Security.addProvider(new BouncyCastleProvider()); // 注册 Bouncy Castle 提供者
    }

    /**
     * 加密 encBizReqData（直接使用 Base64 公钥字符串，不含 PEM 头尾）
     * @param publicKeyBase64  粤焕新提供的公钥（Base64 字符串，无头尾标识）
     * @param jsonData        原始业务 JSON 数据
     */
    public static String encryptBizReqData(String publicKeyBase64, String jsonData) throws Exception {
        // 1. 加载公钥
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        PublicKey publicKey = KeyFactory.getInstance("RSA", "BC").generatePublic(keySpec); // 指定 BC 提供者

        // 2. 使用 RSA/ECB/PKCS1Padding 加密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(jsonData.getBytes(StandardCharsets.UTF_8));

        // 3. 返回 Base64 编码结果
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    /**
     * 生成 sign 签名（直接使用 Base64 私钥字符串，不含 PEM 头尾）
     * @param privateKeyBase64 客户系统的私钥（Base64 字符串，无头尾标识）
     * @param encBizReqData    加密后的 encBizReqData 字符串
     */
    public static String generateSign(String privateKeyBase64, String encBizReqData) throws Exception {
        // 1. 加载私钥
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = KeyFactory.getInstance("RSA", "BC").generatePrivate(keySpec);

        // 2. 使用 SHA256withRSA 签名
        Signature signature = Signature.getInstance("SHA256withRSA", "BC");
        signature.initSign(privateKey);
        signature.update(encBizReqData.getBytes(StandardCharsets.UTF_8));
        byte[] signBytes = signature.sign();

        // 3. 返回 Base64 编码结果
        return Base64.getEncoder().encodeToString(signBytes);
    }

    //------------------------- 解密 encBizRespData -------------------------
    /**
     * 解密 encBizRespData（使用客户系统私钥字符串）
     * @param privateKeyBase64 客户系统的私钥（Base64 字符串，无 PEM 头尾）
     * @param encBizRespData   Base64 加密数据
     * @return 解密后的明文 JSON 字符串
     */
    public static String decryptEncBizRespData(String privateKeyBase64, String encBizRespData)
            throws GeneralSecurityException {

        // 1. 加载客户系统私钥
        PrivateKey privateKey = loadPrivateKey(privateKeyBase64);

        // 2. 解码 Base64 数据
        byte[] encryptedBytes = Base64.getDecoder().decode(encBizRespData);

        // 3. 使用 RSA 私钥解密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

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

    //------------------------- 验证签名 sign -------------------------
    /**
     * 验证签名 sign（使用粤焕新服务端公钥字符串）
     * @param publicKeyBase64 粤焕新服务端的公钥（Base64 字符串，无 PEM 头尾）
     * @param encBizRespData  加密数据原文（Base64 字符串）
     * @param sign            Base64 签名值
     */
    public static boolean verifySign(String publicKeyBase64, String encBizRespData, String sign)
            throws GeneralSecurityException {

        // 1. 加载粤焕新公钥
        PublicKey publicKey = loadPublicKey(publicKeyBase64);

        // 2. 解码签名
        byte[] signatureBytes = Base64.getDecoder().decode(sign);

        // 3. 使用 SHA256withRSA 验证签名（注意文档中 signMsg 参数为 "SHAZ56withRSA"，需确认是否笔误）
        Signature signature = Signature.getInstance("SHA256withRSA", "BC");
        signature.initVerify(publicKey);
        signature.update(encBizRespData.getBytes(StandardCharsets.UTF_8));

        return signature.verify(signatureBytes);
    }

    //------------------------- 密钥加载方法 -------------------------
    // 加载客户系统私钥（Base64 字符串 -> PrivateKey）
    private static PrivateKey loadPrivateKey(String privateKeyBase64) throws GeneralSecurityException {
        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        return KeyFactory.getInstance("RSA", "BC").generatePrivate(keySpec);
    }

    // 加载粤焕新公钥（Base64 字符串 -> PublicKey）
    private static PublicKey loadPublicKey(String publicKeyBase64) throws GeneralSecurityException {
        byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyBase64);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        return KeyFactory.getInstance("RSA", "BC").generatePublic(keySpec);
    }

    public static void main(String[] args) throws Exception {
        boolean isEnc = true;
        if (isEnc) {
            // 示例：密钥为 Base64 字符串（不包含 PEM 头尾）
            String publicKeyBase64 = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuV3tO3C...";  // 粤焕新公钥
            String privateKeyBase64 = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASC..."; // 客户私钥

            // 1. 加密业务数据
            String jsonData = "{\"productCode\":\"A1001\", \"orderId\":\"20231001123456\"}";
            String encBizReqData = encryptBizReqData(publicKeyBase64, jsonData);
            System.out.println("encBizReqData: " + encBizReqData);

            // 2. 生成签名
            String sign = generateSign(privateKeyBase64, encBizReqData);
            System.out.println("sign: " + sign);
        } else {

            try {
                // 示例参数（需替换为实际值）
                String clientPrivateKeyBase64 = "MIIEvQIBADANBgkqhki..."; // 客户私钥 Base64
                String yuehuanxinPublicKeyBase64 = "MIIBIjANBgkqhki..."; // 粤焕新公钥 Base64
                String encBizRespData = "MIIBIjANBgkqhkiG9w0BAQE...";   // 加密数据
                String sign = "Ehc/VlLZ6v4X2...";                       // 签名值

                // 1. 解密数据
                String plainJson = decryptEncBizRespData(clientPrivateKeyBase64, encBizRespData);
                System.out.println("解密后的明文: " + plainJson);

                // 2. 验证签名
                boolean isValid = verifySign(yuehuanxinPublicKeyBase64, encBizRespData, sign);
                System.out.println("签名是否有效? " + isValid);

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

}
