package com.sonic.lion.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.cert.*;
import java.security.interfaces.ECPublicKey;
import java.util.*;

/**
 * Apple StoreKit V2 Webhook 签名验证工具类
 */
@Component
@Slf4j
public class AppleWebhookVerifier {

    /**
     * 证书下载地址：https://www.apple.com/certificateauthority/
     */
    private static final String ROOT_CA_PATH = "certificates/AppleRootCA-G3.cer"; // Apple 根证书路径
    private static final String WWDR_CA_PATH = "certificates/AppleWWDRCAG6.cer"; // Apple WWDR 中间证书路径

    /**
     * 处理 Apple Webhook 通知并验证签名
     * @param jwsToken JWS 格式的 webhook 通知
     * @return 验证结果，成功返回 "Webhook processed successfully"，失败返回错误信息
     */
    public boolean handleAppleWebhook(String jwsToken) {
        try {
            // 解析 JWS
            DecodedJWT jwt = JWT.decode(jwsToken);

            // 获取 x5c 证书链
            String[] x5c = jwt.getHeaderClaim("x5c").asArray(String.class);
            if (x5c == null || x5c.length < 2) {
                log.info("===> handleAppleWebhook : 错误：无效的 x5c 证书链，长度不足");
                return false;
            }

            // 解析证书链并打印调试信息
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            List<X509Certificate> certChain = new ArrayList<>();
            for (int i = 0; i < x5c.length; i++) {
                byte[] certBytes = Base64.getDecoder().decode(x5c[i]);
                X509Certificate cert = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certBytes));
                certChain.add(cert);
                // 打印证书信息
                log.info("证书 " + i + " Subject: " + cert.getSubjectX500Principal());
                log.info("证书 " + i + " Issuer: " + cert.getIssuerX500Principal());
                log.info("证书 " + i + " Serial: " + cert.getSerialNumber());
                log.info("证书 " + i + " 有效期: " + cert.getNotBefore() + " 至 " + cert.getNotAfter());
            }

            // 加载 Apple 根证书和 WWDR G6 中间证书
            X509Certificate rootCert = loadCertificateV2(ROOT_CA_PATH);
            X509Certificate wwdrCert = loadCertificateV2(WWDR_CA_PATH);
            log.info("根证书 Subject: " + rootCert.getSubjectX500Principal());
            log.info("根证书 有效期: " + rootCert.getNotBefore() + " 至 " + rootCert.getNotAfter());
            log.info("WWDR G6 证书 Subject: " + wwdrCert.getSubjectX500Principal());
            log.info("WWDR G6 证书 有效期: " + wwdrCert.getNotBefore() + " 至 " + wwdrCert.getNotAfter());

            // 验证证书链
            try {
                validateCertificateChain(certChain, rootCert, wwdrCert);
            } catch (Exception e) {
                log.info("===> handleAppleWebhook : 错误：证书链验证失败: {}", e.getMessage());
                return false;
            }

            // 验证 JWS 签名
            X509Certificate signingCert = certChain.get(0); // 叶证书
            Algorithm algorithm = Algorithm.ECDSA256((ECPublicKey) signingCert.getPublicKey(), null);
            JWT.require(algorithm).build().verify(jwsToken);

            //返回验证通过的结果
            return true;
        } catch (JWTVerificationException e) {
            log.error("===> handleAppleWebhook : 签名验证失败 :", e);
        } catch (Exception e) {
            log.error("===> handleAppleWebhook : 处理 webhook 失败 :", e);
        }
        return false;
    }

    /**
     * 加载证书文件
     * @param path 证书文件路径
     * @return X509Certificate 证书对象
     * @throws Exception 证书加载失败
     */
    private X509Certificate loadCertificateV2(String path) throws CertificateException, IOException {
        try (InputStream is = getClass().getClassLoader().getResourceAsStream(path)) {
            if (is == null) {
                throw new IOException("证书文件未找到: " + path);
            }
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            return (X509Certificate) cf.generateCertificate(is);
        }
    }

    /**
     * 验证证书链
     * @param certChain x5c 中的证书链
     * @param rootCert Apple 根证书
     * @param wwdrCert Apple WWDR G6 中间证书
     * @throws Exception 证书链验证失败
     */
    private void validateCertificateChain(List<X509Certificate> certChain, X509Certificate rootCert, X509Certificate wwdrCert)
            throws Exception {
        // 创建信任锚
        TrustAnchor trustAnchor = new TrustAnchor(rootCert, null);
        Set<TrustAnchor> trustAnchors = new HashSet<>();
        trustAnchors.add(trustAnchor);

        // 构建验证链：使用 x5c 中的叶证书和中间证书
        List<X509Certificate> validationChain = new ArrayList<>();
        validationChain.add(certChain.get(0)); // 叶证书
        if (certChain.size() > 1) {
            validationChain.add(certChain.get(1)); // WWDR CA G6
        }

        // 创建 CertPath
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        CertPath certPath = cf.generateCertPath(validationChain);

        // 配置 PKIX 参数
        PKIXParameters params = new PKIXParameters(trustAnchors);
        params.setRevocationEnabled(false); // Apple 证书不使用 CRL/OCSP
        params.setDate(null); // 使用当前时间验证

        // 执行证书链验证
        try {
            CertPathValidator validator = CertPathValidator.getInstance("PKIX");
            validator.validate(certPath, params);
            log.info("证书链验证成功");
        } catch (CertPathValidatorException e) {
            System.err.println("证书链验证失败: " + e.getMessage());
            throw e;
        }
    }

}