package com.ruoyi.common.pay.tm;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.pay.tm.vo.RefundInfo;
import com.ruoyi.common.pay.tm.vo.TmTradeInfo;
import com.ruoyi.common.pay.wx.Payable;
import com.ruoyi.common.pay.wx.RefundAble;
import com.ruoyi.common.utils.http.HttpUtils;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 太米支付
 */
@Service
public class TmPayService {

    private final static String SIGNKEY = "b4ixpiogfj5vu3tbkv23gj0dvo2j2ksz";
    private static final Logger log = LoggerFactory.getLogger(TmPayService.class);

    /**
     * 订单查询
     */
    public static TmTradeInfo orderQuery(IChannelInfo channel, String outTradeNo) {
        HashMap<String, Object> body = new HashMap<>();
        body.put("outTradeId", outTradeNo);
        body.put("terminalType", "1");
        body.put("shopId", channel.getShopId());
        String response = doPost(channel.getHttpUrl() + "/open/Pay/orderQuery", body,channel);
        if (com.ruoyi.common.utils.StringUtils.hasText(response)) {
            JSONObject jsonResponse = JSON.parseObject(response);
            if (jsonResponse.getInteger("errCode") == 0 && "ok".equals(jsonResponse.getString("errMsg"))) {
                JSONObject tradeInfo = jsonResponse.getJSONObject("tradeInfo");
                return tradeInfo.toJavaObject(TmTradeInfo.class);
            } else {
                throw new ServiceException("订单查询失败: " + jsonResponse.getString("errMsg"));
            }
        }
        throw new ServiceException("订单查询数据为空");
    }

    /**
     * 退款
     */
    public static RefundInfo refund(IChannelInfo channel,RefundAble refundAble) {
        HashMap<String, Object> body = new HashMap<>();
        body.put("refundFee", String.valueOf(refundAble.getAmount()));
        body.put("terminalType", "1");
        body.put("outTradeId", refundAble.getOutTradeNo());
        body.put("shopId", channel.getShopId());
        String response = doPost(channel.getHttpUrl() + "/open/Pay/refund", body,channel);
        if (com.ruoyi.common.utils.StringUtils.hasText(response)) {
            JSONObject jsonResponse = JSON.parseObject(response);
            if (jsonResponse.getInteger("errCode") == 0 && "退款成功".equals(jsonResponse.getString("errMsg"))) {
                JSONObject tradeInfo = jsonResponse.getJSONObject("refundInfo");
                return tradeInfo.toJavaObject(RefundInfo.class);
            } else {
                throw new ServiceException("退款失败: " + jsonResponse.getString("errMsg"));
            }
        }
        throw new ServiceException("退款数据为空");
    }

    /**
     * 关闭订单
     */
    public static void closeOrder(String outTradeNo,IChannelInfo channel) {
        HashMap<String, Object> body = new HashMap<>();
        body.put("outTradeId", outTradeNo);
        body.put("terminalType", "1");
        body.put("shopId", channel.getShopId());
        String response = doPost(channel.getHttpUrl() + "/open/Pay/orderClose", body, channel);
        if (com.ruoyi.common.utils.StringUtils.hasText(response)) {
            JSONObject jsonResponse = JSON.parseObject(response);
            if (jsonResponse.getInteger("errCode") != 0) {
                throw new ServiceException("关闭订单失败: " + jsonResponse.getString("errMsg"));
            }
        }else{
            throw new ServiceException("关闭订单数据为空");
        }
    }

    /**
     * 小程序支付
     */
    public static PrepayWithRequestPaymentResponse pay(IChannelInfo channel, Payable payable) {
        HashMap<String, Object> body = new HashMap<>();
        body.put("payAmount", String.valueOf(payable.getAmount()));
        body.put("terminalType", "1");
        body.put("shopId", channel.getShopId());  // 从渠道获取shopId
        body.put("sn", channel.getSn());
        body.put("payType", "wx_pay");
        body.put("outTradeId", payable.getOutTradeNo());
        body.put("body", payable.getDescription());
        body.put("notifyUrl", channel.getNotifyUrl());
        body.put("openid", payable.getOpenid());
        String response = doPost(channel.getHttpUrl() + "/open/Pay/miniPay", body, channel);

        if (com.ruoyi.common.utils.StringUtils.hasText(response)) {
            // 解析 response，提取 "params" 字段
            JSONObject jsonResponse = JSON.parseObject(response);
            if (jsonResponse.getInteger("errCode") == 0 && "ok".equals(jsonResponse.getString("errMsg"))) {
                // 提取 "params" 并转成 PrepayWithRequestPaymentResponse 对象
                JSONObject params = jsonResponse.getJSONObject("params");
                return params.toJavaObject(PrepayWithRequestPaymentResponse.class);
            } else {
                throw new ServiceException("支付失败: " + jsonResponse.getString("errMsg"));
            }
        }
        throw new ServiceException("支付数据为空");
    }



    private static String doPost(String url, HashMap<String, Object> body, IChannelInfo channel) {
        body.put("developerId", channel.getDeveloperId());
        body.put("version", "1.0");
        body.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
        body.put("nonceStr", TmPayUtil.getRandomString(16));

        String bodyStr = TmPayUtil.getAsciiSort(body);
        String sign = TmPayUtil.getMD5Code(bodyStr + "&key=" + channel.getSignKey()).toUpperCase();
        body.put("sign", sign);

        HashMap<String, String> headerData = new HashMap<>();
        headerData.put("Content-Type", "application/json");

        String response = HttpUtils.sendPostWithHeaders(url, headerData, JSON.toJSONString(body));
        log.info("doPost请求API响应: " + response);
        return response;
    }

    public boolean validSign(Map<String, Object> params) {
        // 获取传递过来的签名
        String receivedSign = (String)params.get("sign");
        // 获取签名字段
        System.out.println("获取到的签名-------------:"+receivedSign);
        if (receivedSign == null) {
            return false;  // 如果没有传递签名，验签失败
        }
        // 移除签名字段后，重新生成签名
        params.remove("sign");
        // 按照请求时的签名逻辑，生成签名字符串
        String paramsStr = TmPayUtil.getAsciiSort(params);  // 按ASCII排序
        String generatedSign = TmPayUtil.getMD5Code(paramsStr + "&key=" + SIGNKEY).toUpperCase();  // 重新生成签名
        System.out.println("新生成的签名-----------:"+generatedSign);
        // 比较签名是否一致
        return generatedSign.equals(receivedSign);
    }

}
