package com.ruoyi.xq.controller.app;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.xq.config.WxPayProperties;
import com.ruoyi.xq.dto.app.pay.PayControllerDTO;
import com.ruoyi.xq.dto.app.pay.PayOrderInfoDTO;
import com.ruoyi.xq.dto.app.pay.PayReturnResp;
import com.ruoyi.xq.enums.pay.PlatformTypeEnum;
import com.ruoyi.xq.manager.PayManager;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/pay")
@Tag(name = "支付相关的接口")
@Validated
@Slf4j
public class PayController {

    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private PayManager payManager;

    private static final String NOTIFY_WX_URL = "/api/pay/wx/notify";
    private static final String NOTIFY_ALI_URL = "/api/pay/ali/notify";

    @PostMapping(value = "/jsapi/wx")
    @Operation(summary = "微信支付-公众号")
    @Log(title = "微信支付-公众号", businessType = BusinessType.OTHER, isSaveDb = true)
    public R<PayReturnResp> jsapiPay(@RequestBody PayControllerDTO payController){
        PayOrderInfoDTO payOrderInfo = payManager.getOrderInfo(payController.getOrderNo());
        String openId = payController.getOpenId();
        if (StrUtil.isEmpty(openId)) {
            return R.fail("openid is null");
        }
        String ip = ServletUtils.getClientIP();
        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayProperties.getAppId())
                .mch_id(wxPayProperties.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body(payOrderInfo.getBody())
                .out_trade_no(WxPayKit.generateStr())
                .total_fee(payOrderInfo.getPriceFenStr())
                .spbill_create_ip(ip)
                .notify_url(wxPayProperties.getNotifyUrl()+NOTIFY_WX_URL)
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayProperties.getPartnerKey(), SignType.HMACSHA256);
        String xmlResult = WxPayApi.pushOrder(false, params);
        log.info(xmlResult);
        Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
        String returnCode = resultMap.get("return_code");
        String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            log.error("j微信支付失败 returnMsg={}",returnMsg);
            return R.fail("微信支付失败，请联系客服");
        }
        String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            log.error("j微信支付失败 returnMsg={}",returnMsg);
            return R.fail("微信支付失败，请联系客服");
        }
        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
        String prepayId = resultMap.get("prepay_id");
        Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayProperties.getAppId(),
                wxPayProperties.getPartnerKey(), SignType.HMACSHA256);
        String jsonStr = JSON.toJSONString(packageParams);
        PayReturnResp resp = new PayReturnResp();
        resp.setData(jsonStr);
        return R.ok(resp);
    }


    @PostMapping(value = "/wx/notify")
    @Operation(hidden = true)
    @Log(title = "微信回调", businessType = BusinessType.OTHER, isSaveDb = false)
    @SaIgnore
    public String payNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        log.info("支付通知=" + xmlMsg);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
        String returnCode = params.get("return_code");
        String mchId = params.get("mch_id");
        if(!wxPayProperties.getMchId().equals(mchId)){
            log.error("未找到微信配置 mchId={}",mchId);
            return null;
        }
        // 注意重复通知的情况，同一订单号可能收到多次通知，请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, wxPayProperties.getPartnerKey(), SignType.MD5)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                String outTradeNo = params.get("out_trade_no");
                String transactionId = params.get("transaction_id");
                payManager.callBack(outTradeNo,params,mchId, PlatformTypeEnum.WX);
                Map<String, String> xml = new HashMap<>(2);
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
                return WxPayKit.toXml(xml);
            }
        }
        return null;
    }



}
