package com.zsElectric.boot.core.pay;

import com.aliyun.oss.ServiceException;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.*;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders;
import com.wechat.pay.contrib.apache.httpclient.notification.Notification;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import com.zsElectric.boot.common.util.StringUtils;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Component
public class WechatPayV3Utils {

    private CloseableHttpClient httpClient;
    private Verifier verifier;
    private PrivateKey merchantPrivateKey;
    private Gson gson = new Gson();


    // 初始化证书和客户端
    @PostConstruct
    public void init() {
        try {
            // 加载商户私钥
            setMerchantPrivateKey();
            // 初始化验证器
            setVerifier();
            // 初始化HTTP客户端
            setHttpClient();
            log.info("微信支付初始化成功");
        } catch (Exception e) {
            log.error("微信支付初始化失败", e);
        }
    }

    /**
     * 加载商户私钥
     */
    private void setMerchantPrivateKey() {
        try {
            // 如果WECHAT_MCH_PRIVATE_KEY是文件路径
            if (StringUtils.isNotEmpty(WechatConstants.WECHAT_MCH_PRIVATE_KEY)) {
                // 如果是文件路径，从文件加载
                if (WechatConstants.WECHAT_MCH_PRIVATE_KEY.endsWith(".pem")) {
                    InputStream inputStream = new FileInputStream(WechatConstants.WECHAT_MCH_PRIVATE_KEY);
                    this.merchantPrivateKey = PemUtil.loadPrivateKey(inputStream);
                } else {
                    // 如果是私钥内容字符串，直接从字符串加载
                    this.merchantPrivateKey = PemUtil.loadPrivateKey(WechatConstants.WECHAT_MCH_PRIVATE_KEY);
                }
            } else {
                log.warn("微信商户私钥未配置");
            }
        } catch (Exception e) {
            log.error("加载商户私钥失败", e);
            throw new RuntimeException("加载商户私钥失败", e);
        }
    }

    /**
     * 获取微信证书
     *
     * @throws Exception
     */
    private void setVerifier() throws Exception {
        if (merchantPrivateKey == null) {
            setMerchantPrivateKey();
        }
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        certificatesManager.putMerchant(WechatConstants.WECHAT_MCH_ID,
                new WechatPay2Credentials(WechatConstants.WECHAT_MCH_ID, new PrivateKeySigner(WechatConstants.WECHAT_MCH_SERIAL_NUM, merchantPrivateKey)),
                WechatConstants.WECHAT_MCH_SECRET_V3.getBytes(StandardCharsets.UTF_8));
        // ... 若有多个商户号，可继续调用putMerchant添加商户信息

        // 从证书管理器中获取verifier
        verifier = certificatesManager.getVerifier(WechatConstants.WECHAT_MCH_ID);
    }

    /**
     * 创建请求客户端
     *
     * @throws Exception
     */
    private void setHttpClient() throws Exception {
        if (verifier == null) {
            setVerifier();
        }
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(WechatConstants.WECHAT_MCH_ID, WechatConstants.WECHAT_MCH_SERIAL_NUM, merchantPrivateKey)
                .withValidator(response -> true);
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient

        httpClient = builder.build();
    }

    /**
     * 发送POST请求
     *
     * @param url    请求地址
     * @param params json参数
     * @return
     */
    public JsonObject sendPost(String url, JsonObject params) {
        try {
            if (httpClient == null) {
                setHttpClient();
            }
            HttpPost httpPost = new HttpPost(url);
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");
            httpPost.setEntity(new StringEntity(gson.toJson(params), StandardCharsets.UTF_8));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            log.info("微信返回的内容：" + bodyAsString);
            if (StringUtils.isEmpty(bodyAsString)) {
                return null;
            }
            return gson.fromJson(bodyAsString, JsonObject.class);
        } catch (Exception e) {
            log.error("微信支付V3请求失败");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 发送get请求
     *
     * @param url 请求地址 参数直接在地址上拼接
     * @return
     */
    public JsonObject sendGet(String url) {
        try {
            if (httpClient == null) {
                setHttpClient();
            }
            URIBuilder uriBuilder = new URIBuilder(url);
            HttpGet httpGet = new HttpGet(uriBuilder.build());
            httpGet.addHeader("Accept", "application/json");
            CloseableHttpResponse response = httpClient.execute(httpGet);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            log.info("微信返回的内容：" + bodyAsString);
            if (StringUtils.isEmpty(bodyAsString)) {
                return null;
            }
            return gson.fromJson(bodyAsString, JsonObject.class);
        } catch (Exception e) {
            log.error("微信支付V3请求失败");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 回调通知验签与解密
     *
     * @param request
     * @return
     */
    public JsonObject getCallbackData(HttpServletRequest request) {
        try {
            if (verifier == null) {
                setVerifier();
            }
            String wechatPaySerial = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SERIAL);
            String nonce = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_NONCE);
            String timestamp = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_TIMESTAMP);
            String signature = request.getHeader(WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE);
            String body;
            BufferedReader reader = request.getReader();
            String line ;
            StringBuilder inputString = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            body = inputString.toString();
            log.info("body数据："+body);
            reader.close();
            // 构建request，传入必要参数
            NotificationRequest res = new NotificationRequest.Builder().withSerialNumber(wechatPaySerial)
                    .withNonce(nonce)
                    .withTimestamp(timestamp)
                    .withSignature(signature)
                    .withBody(body)
                    .build();
            NotificationHandler handler = new NotificationHandler(verifier, WechatConstants.WECHAT_MCH_SECRET_V3.getBytes(StandardCharsets.UTF_8));
            // 验签和解析请求体
            Notification notification = handler.parse(res);
            log.info("回调通知数据：" + notification.toString());
            // 解析开数据
            String decryptData = notification.getDecryptData();
            log.info("回调解析数据：" + decryptData);
            if (StringUtils.isEmpty(decryptData)) {
                return null;
            }
            return gson.fromJson(decryptData, JsonObject.class);
        } catch (Exception e) {
            log.error("微信支付V3回调失败");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 微信支付v3签名 RSA签名
     *
     * @param message 要签名的字符串
     * @return
     */
    public String signRSA(String message) {
        try {
            if (merchantPrivateKey == null) {
                setMerchantPrivateKey();
            }
            Signer signer = new PrivateKeySigner(WechatConstants.WECHAT_MCH_SERIAL_NUM, merchantPrivateKey);
            Signer.SignatureResult signature = signer.sign(message.getBytes(StandardCharsets.UTF_8));
            return signature.getSign();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }
}