package com.ruoyi.common.pay.wx.service;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.pay.wx.config.WxPayConfig;
import com.ruoyi.common.pay.wx.domain.*;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 微信支付服务
 * @author 辉
 * 2024/3/11
 */
@Service
@Slf4j
public class WxPayService {

    @Autowired
    private JsapiService jsapiService;

    @Autowired
    private JsapiServiceExtension jsapiServiceExtension;

    @Autowired
    private WxPayConfig wxPayConfig;

    @Autowired
    private RefundService refundService;

    private static final String CNY = "CNY";

    public PrepayWithRequestPaymentResponse prepayWithRequestPayment(Payable payable) {
        return this.prepayWithRequestPayment(payable.payableOutTradeNo(), payable.payableMoney(), payable.payableDescription(), payable.payableOpenId(), payable.payableAttach());
    }

    public PrepayWithRequestPaymentResponse prepayWithRequestPayment(String billNo, BigDecimal money, String description, String wxOpenId, String attach) {
        // 获取JSAPI所需参数
        PrepayRequest request = new PrepayRequest();
        request.setAmount(getAmount(money));
        request.setOutTradeNo(billNo);
        request.setAppid(wxPayConfig.getAppId());
        request.setMchid(wxPayConfig.getMerchantId());
        request.setDescription(description);
        request.setNotifyUrl(wxPayConfig.getNotifyUrl());
        request.setPayer(getPayer(wxOpenId));
        request.setAttach(attach);
        return jsapiServiceExtension.prepayWithRequestPayment(request);
    }

    /**
     * 关闭支付订单
     * @param billNo 平台订单编号
     */
    public void closeOrder(String billNo) {
        CloseOrderRequest request = new CloseOrderRequest();
        request.setMchid(wxPayConfig.getMerchantId());
        request.setOutTradeNo(billNo);
        jsapiService.closeOrder(request);
    }

    public Transaction queryOrderById(String prePayId) {
        QueryOrderByIdRequest request = new QueryOrderByIdRequest();
        request.setMchid(wxPayConfig.getMerchantId());
        request.setTransactionId(prePayId);
        return jsapiService.queryOrderById(request);
    }

    public Transaction queryOrderByOutTradeNo(String billNo) {
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(wxPayConfig.getMerchantId());
        request.setOutTradeNo(billNo);
        return jsapiService.queryOrderByOutTradeNo(request);
    }

    /**
     * 发起退款
     *
     * @param refund
     */
    public Refund refund(RefundAble refund) {
        CreateRequest request = new CreateRequest();
        request.setOutTradeNo(refund.refundOutTradeNo());
        request.setOutRefundNo(refund.refundOutRefundNo());
        request.setReason(refund.refundReason());
        request.setAmount(refund.refundAmount());
        request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());
        log.info("【退款】请求微信参数: {}", JSON.toJSONString(request));
        Refund res = refundService.create(request);
        log.info("【退款】微信返回结果:【{}】",JSON.toJSONString(refund));
        return res;
    }

    private Payer getPayer(String openId) {
        Payer payer = new Payer();
        payer.setOpenid(openId);
        return payer;
    }

    private Amount getAmount(BigDecimal money) {
        Amount amount = new Amount();
        amount.setTotal(money.intValue());
        amount.setCurrency(CNY);
        return amount;
    }

}
