package com.wzj.soopin.transaction.service.impl;

import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.cipher.PrivacyDecryptor;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.http.*;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferRequestNew;
import com.wzj.soopin.transaction.domain.entity.InitiateBatchTransferResponseNew;
import com.wzj.soopin.transaction.domain.entity.TransferBillEntity;
import com.wzj.soopin.transaction.domain.entity.TransferDetailEntityNew;
import com.wzj.soopin.transaction.wechat.WechatPayConfig;
import jakarta.servlet.http.HttpServletRequest;
import org.dromara.common.core.exception.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信支付 Api相关
 *
 * @author: jsy
 * @date: 2025/02/13  11:30
 */
@Service
public class WxPayService {

    private static final Logger logger = LoggerFactory.getLogger(WxPayService.class);
    @Autowired
    private WechatPayConfig WechatPayConfig;

    /**
     * 商家转账 - 发起转账 - 2025年1月15号之后，商户转账零线必须用户确认收款
     *
     * @param request 请求体
     * @return
     */
    public InitiateBatchTransferResponseNew initiateBatchTransferNew(InitiateBatchTransferRequestNew request) {
        logger.info("WxPayService.initiateBatchTransferNew request:{}", request.toString());
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(WechatPayConfig.getMchId())
                .privateKeyFromPath(WechatPayConfig.getPrivateKeyPath())
                .merchantSerialNumber(WechatPayConfig.getMchSerialNo())
                .apiV3Key(WechatPayConfig.getApiV3Key())
                .build();
        String encryptName = config.createEncryptor().encrypt(request.getUserName());
        request.setUserName(encryptName);
        String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills";
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Wechatpay-Serial", config.createEncryptor().getWechatpaySerial());
        HttpRequest httpRequest =
                new HttpRequest.Builder()
                        .httpMethod(HttpMethod.POST)
                        .url(requestPath)
                        .headers(headers)
                        .body(createRequestBody(request))
                        .build();
        HttpClient httpClient = new DefaultHttpClientBuilder().config(config).build();
        HttpResponse<InitiateBatchTransferResponseNew> httpResponse = httpClient.execute(httpRequest, InitiateBatchTransferResponseNew.class);
        logger.info("WxPayService.initiateBatchTransferNew response:{}", httpResponse.getServiceResponse());
        return httpResponse.getServiceResponse();
    }

    /**
     * 商家转账 - 商户单号查询转账单 - 2025年1月15号之后，商家转账用户确认模式下，根据商户单号查询转账单的详细信息
     *
     * @param outBillNo 商户系统内部的商家单号
     * @return
     */
    public TransferDetailEntityNew getTransferDetailByOutNoNew(String outBillNo) {
        logger.info("WxPayService.getTransferDetailByOutNoNew request:{}", outBillNo);
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(WechatPayConfig.getMchId())
                .privateKeyFromPath(WechatPayConfig.getPrivateKeyPath())
                .merchantSerialNumber(WechatPayConfig.getMchSerialNo())
                .apiV3Key(WechatPayConfig.getApiV3Key())
                .build();
        String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}";
        requestPath = requestPath.replace("{out_bill_no}", UrlEncoder.urlEncode(outBillNo));
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
        HttpRequest httpRequest =
                new HttpRequest.Builder()
                        .httpMethod(HttpMethod.GET)
                        .url(requestPath)
                        .headers(headers)
                        .build();
        PrivacyDecryptor decryptor = config.createDecryptor();
        HttpClient httpClient = new DefaultHttpClientBuilder().config(config).build();
        HttpResponse<TransferDetailEntityNew> httpResponse = httpClient.execute(httpRequest, TransferDetailEntityNew.class);
        logger.info("WxPayService.getTransferDetailByOutNoNew response:{}", httpResponse.getServiceResponse());
        return httpResponse.getServiceResponse().cloneWithCipher(decryptor);
    }

    /**
     * 转json
     *
     * @param request 请求体
     * @return
     */
    private static RequestBody createRequestBody(Object request) {
        return new JsonRequestBody.Builder().body(new Gson().toJson(request)).build();
    }

    /**
     * 商家转账 - 零钱提现 - 回调通知
     *
     * @param request
     * @return
     */
    public TransferDetailEntityNew wxPaySuccessCallback(HttpServletRequest request) {
        String requestBody = getBodyString(request, "UTF-8");
        //证书序列号（微信平台）   验签的“微信支付平台证书”所对应的平台证书序列号
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        //微信传递过来的签名   验签的签名值
        String wechatSignature = request.getHeader("Wechatpay-Signature");
        //验签的时间戳
        String wechatTimestamp = request.getHeader("Wechatpay-Timestamp");
        //验签的随机字符串
        String wechatpayNonce = request.getHeader("Wechatpay-Nonce");
        // 1. 构造 RequestParam
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(wechatPaySerial)
                .nonce(wechatpayNonce)
                .signature(wechatSignature)
                .timestamp(wechatTimestamp)
                .body(requestBody)
                .build();
        // 2. 构建Config RSAAutoCertificateConfig
        Config config = new RSAAutoCertificateConfig.Builder()
                .merchantId(WechatPayConfig.getMchId())
                .privateKeyFromPath(WechatPayConfig.getPrivateKeyPath())
                .merchantSerialNumber(WechatPayConfig.getMchSerialNo())
                .apiV3Key(WechatPayConfig.getApiV3Key())
                .build();
        logger.info("WxPayService.wxPaySuccessCallback request : wechatPaySerial is [{}]  , wechatSignature is [{}] , wechatTimestamp is [{}] , wechatpayNonce  is [{}] , requestBody is [{}]",wechatPaySerial,wechatSignature,wechatTimestamp,wechatpayNonce,requestBody);
        // 3. 初始化 NotificationParser
        NotificationParser parser = new NotificationParser((NotificationConfig) config);
        try {
            TransferDetailEntityNew entity = parser.parse(requestParam, TransferDetailEntityNew.class);
            logger.info("WxPayService.wxPaySuccessCallback responseBody: {}", entity != null ? JSON.toJSONString(entity) : null);
            return entity;
        } catch (ValidationException e) {
            logger.error("Sign verification failed", e);
            throw new SecurityException("签名验证失败");
        } catch (Exception e) {
            logger.error("Exception occurred while processing", e);
            throw new SecurityException("系统内部错误");
        }
    }

    /**
     * 获取post请求中的Body
     *
     * @param request httpRequest
     * @return body字符串
     */
    public static String getBodyString(HttpServletRequest request, String charSet) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            //读取流并将流写出去,避免数据流中断;
            reader = new BufferedReader(new InputStreamReader(inputStream, charSet));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            logger.error("获取requestBody异常", e);
        } finally {
            IoUtil.close(inputStream);
            IoUtil.close(reader);
        }
        return sb.toString();
    }

    /**
     * 撤销转账
     *
     * @param outBillNo 商户系统内部的商家单号
     * @return
     */
    public TransferBillEntity cancelBatchTransfer(String outBillNo) {
        logger.info("WxPayService.cancelBatchTransfer request: outBillNo={}", outBillNo);
        Config config = new RSAAutoCertificateConfig.Builder()
            .merchantId(WechatPayConfig.getMchId())
            .privateKeyFromPath(WechatPayConfig.getPrivateKeyPath())
            .merchantSerialNumber(WechatPayConfig.getMchSerialNo())
            .apiV3Key(WechatPayConfig.getApiV3Key())
            .build();
        String requestPath = "https://api.mch.weixin.qq.com/v3/fund-app/mch-transfer/transfer-bills/out-bill-no/{out_bill_no}/cancel";
        requestPath = requestPath.replace("{out_bill_no}", UrlEncoder.urlEncode(outBillNo));
        HttpHeaders headers = new HttpHeaders();
        headers.addHeader("Accept", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Content-Type", MediaType.APPLICATION_JSON.getValue());
        headers.addHeader("Wechatpay-Serial", config.createEncryptor().getWechatpaySerial());
        Map<String, String> requestBodyMap = new HashMap<>();
        String requestBodyJson = new Gson().toJson(requestBodyMap);
        logger.debug("WxPayService.cancelBatchTransfer requestBody: {}", requestBodyJson);
        HttpRequest httpRequest =
            new HttpRequest.Builder()
                .httpMethod(HttpMethod.POST)
                .url(requestPath)
                .headers(headers)
                .body(new JsonRequestBody.Builder().body(requestBodyJson).build())
                .build();
        HttpClient httpClient = new DefaultHttpClientBuilder().config(config).build();
        try {
            HttpResponse<String> httpResponse = httpClient.execute(httpRequest, String.class);
            logger.info("WxPayService.cancelBatchTransfer response: {}", httpResponse.getServiceResponse());
            // 确保返回的数据是正确的 JSON 解析结果
            return JSON.parseObject(httpResponse.getServiceResponse(), TransferBillEntity.class);
        } catch (ServiceException e) {
            logger.error("WxPayService.cancelBatchTransfer ServiceException: {}", e.getMessage());
            throw new SecurityException("服务异常: " + e.getMessage());
        } catch (Exception e) {
            logger.error("WxPayService.cancelBatchTransfer Exception: {}", e.getMessage());
            throw new SecurityException("系统内部错误: " + e.getMessage());
        }
    }



}

