package com.hotwj.platform.pay.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import org.dromara.common.core.exception.ServiceException;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

public final class PayCryptoUtils {

    private PayCryptoUtils() {
    }

    public static PrivateKey loadPrivateKey(String pemText) {
        try {
            String normalized = normalizePem(pemText)
                    .replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");
            byte[] decoded = Base64.decode(normalized);
            return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        } catch (Exception e) {
            throw new ServiceException("解析商户私钥失败: " + e.getMessage());
        }
    }

    public static PublicKey loadPublicKey(String pemText) {
        try {
            String normalized = normalizePem(pemText)
                    .replace("-----BEGIN PUBLIC KEY-----", "")
                    .replace("-----END PUBLIC KEY-----", "")
                    .replaceAll("\\s+", "");
            byte[] decoded = Base64.decode(normalized);
            return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        } catch (Exception e) {
            throw new ServiceException("解析平台公钥失败: " + e.getMessage());
        }
    }

    public static String rsaSign(String content, String privateKeyPem) {
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(loadPrivateKey(privateKeyPem));
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            return Base64.encode(signature.sign());
        } catch (Exception e) {
            throw new ServiceException("RSA 签名失败: " + e.getMessage());
        }
    }

    public static boolean rsaVerify(String content, String sign, String publicKeyPem) {
        try {
            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initVerify(loadPublicKey(publicKeyPem));
            signature.update(content.getBytes(StandardCharsets.UTF_8));
            return signature.verify(Base64.decode(sign));
        } catch (Exception e) {
            throw new ServiceException("RSA 验签失败: " + e.getMessage());
        }
    }

    public static String aesGcmDecrypt(String apiV3Key, String associatedData, String nonce, String cipherText) {
        try {
            Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            SecretKeySpec keySpec = new SecretKeySpec(apiV3Key.getBytes(StandardCharsets.UTF_8), "AES");
            GCMParameterSpec gcm = new GCMParameterSpec(128, nonce.getBytes(StandardCharsets.UTF_8));
            cipher.init(Cipher.DECRYPT_MODE, keySpec, gcm);
            if (StrUtil.isNotBlank(associatedData)) {
                cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8));
            }
            byte[] plain = cipher.doFinal(Base64.decode(cipherText));
            return new String(plain, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new ServiceException("微信回调解密失败: " + e.getMessage());
        }
    }

    private static String normalizePem(String text) {
        if (StrUtil.isBlank(text)) {
            throw new ServiceException("支付密钥配置不能为空");
        }
        return text.replace("\\n", "\n").trim();
    }
}
