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.PayApi;
import com.ruoyi.common.pay.Payable;
import com.ruoyi.common.pay.Refundable;
import com.ruoyi.common.pay.tm.config.TmPayConfig;
import com.ruoyi.common.pay.tm.enums.TmPayStatus;
import com.ruoyi.common.pay.tm.vo.RefundInfo;
import com.ruoyi.common.pay.tm.vo.TmTradeInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.http.HttpUtils;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

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

    /**
     * 订单查询
     */
    public TmTradeInfo queryByOutTradeNo(String outTradeNo, LocalDate orderDate, Object tmConfig) {
        // 初始化配置
        TmPayConfig config = (TmPayConfig) tmConfig;

        HashMap<String, Object> body = new HashMap<>();
        body.put("outTradeId", outTradeNo);
        body.put("terminalType", "1");
        body.put("shopId", config.getShopId());
        String response = doPost(config.getHttpUrl() + "/open/Pay/orderQuery", body, config);
        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");
                TmTradeInfo tmTradeInfo = tradeInfo.toJavaObject(TmTradeInfo.class);
                return tmTradeInfo;
            } else {
                throw new ServiceException("订单查询失败: " + jsonResponse.getString("errMsg"));
            }
        }
        throw new ServiceException("订单查询数据为空");
    }

    /**
     * 退款
     */
    public RefundInfo refund(Refundable refundAble, Object tmConfig) {
        // 初始化配置
        TmPayConfig config = (TmPayConfig) tmConfig;

        HashMap<String, Object> body = new HashMap<>();
        body.put("refundFee", String.valueOf(refundAble.refundAmount().getRefund()));
        body.put("terminalType", "1");
        body.put("outTradeId", refundAble.refundOutTradeNo());
        body.put("shopId", config.getShopId());
        String response = doPost(config.getHttpUrl() + "/open/Pay/refund", body, config);
        if (com.ruoyi.common.utils.StringUtils.hasText(response)) {
            JSONObject jsonResponse = JSON.parseObject(response);
            if (jsonResponse.getInteger("errCode") == 0) {
                JSONObject refundInfo = jsonResponse.getJSONObject("refundInfo");
                ServiceUtil.assertion(refundInfo == null, "退款失败");
                ServiceUtil.assertion(refundInfo.getInteger("refundStatus") != 1, "退款失败:%s", refundInfo.getString("refundMessage"));
                return refundInfo.toJavaObject(RefundInfo.class);
            } else {
                throw new ServiceException("退款失败: " + jsonResponse.getString("errMsg"));
            }
        }
        throw new ServiceException("退款数据为空");
    }

    @Override
    public boolean isPaySuccessByOutTradeNo(String outTradeNo, LocalDate orderDate, Object config) {
        TmTradeInfo result = queryByOutTradeNo(outTradeNo, orderDate, config);
        return isPaySuccess(result);
    }

    @Override
    public boolean isPaySuccess(Object result) {
        TmTradeInfo res = (TmTradeInfo) result;
        return res != null && TmPayStatus.isSuccess(res.getPayStatus());
    }

    @Override
    public LocalDateTime getPayTime(Object result) {
        TmTradeInfo res = (TmTradeInfo) result;
        return DateUtils.toLocalDateTime(res.getPayTime(), "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 关闭订单
     */
    public void closeByOutTradeNo(String outTradeNo, Object tmConfig) {
        // 初始化配置
        TmPayConfig config = (TmPayConfig) tmConfig;

        HashMap<String, Object> body = new HashMap<>();
        body.put("outTradeId", outTradeNo);
        body.put("terminalType", "1");
        body.put("shopId", config.getShopId());
        String response = doPost(config.getHttpUrl() + "/open/Pay/orderClose", body, config);
        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 PrepayWithRequestPaymentResponse pay(Payable payable, Object tmConfig) {
        // 初始化配置
        TmPayConfig config = (TmPayConfig) tmConfig;

        HashMap<String, Object> body = new HashMap<>();
        body.put("payAmount", String.valueOf(payable.payableFen()));
        body.put("terminalType", "1");
        body.put("shopId", config.getShopId());  // 从渠道获取shopId
        body.put("sn", null);
        body.put("payType", "wx_pay");
        body.put("outTradeId", payable.payableOutTradeNo());
        body.put("body", payable.payableDescription());
        body.put("notifyUrl", config.getNotifyUrl());
        body.put("openid", payable.payableOpenId());
        String response = doPost(config.getHttpUrl() + "/open/Pay/miniPay", body, config);

        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");
                PrepayWithRequestPaymentResponse paymentResponse = params.toJavaObject(PrepayWithRequestPaymentResponse.class);
                return paymentResponse;
            } else {
                throw new ServiceException("支付失败: " + jsonResponse.getString("errMsg"));
            }
        }
        throw new ServiceException("支付数据为空");
    }



    private static String doPost(String url, HashMap<String, Object> body, TmPayConfig config) {
        body.put("developerId", config.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=" + config.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));
        return response;
    }

    public boolean validSign(Map<String, Object> params, String signKey) {


        // 获取传递过来的签名
        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);
    }

}
