package com.czg;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import com.czg.entity.CzgBaseReqParams;
import com.czg.entity.CzgBaseRespParams;
import com.czg.entity.req.*;
import com.czg.entity.resp.*;
import com.czg.enums.CzgPayEnum;
import com.czg.resp.CzgResult;
import com.czg.utils.AssertUtil;
import com.czg.utils.MD5Util;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * @author ww
 * @description 超掌柜支付类
 */
@Slf4j
public class CzgPayUtils {

    /**
     * h5支付
     *
     * @param domain    域名
     * @param appId     应用id tb_shop_merchant 表中的 app_id
     * @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
     */
    public static CzgResult<CzgH5PayResp> h5Pay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgH5PayReq bizData) {
        return sendCzg(domain.concat(CzgPayEnum.H5PAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgH5PayResp.class);
    }

    /**
     * js支付
     *
     * @param domain    域名
     * @param appId     应用id tb_shop_merchant 表中的 app_id
     * @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
     */
    public static CzgResult<CzgJsPayResp> jsPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgJsPayReq bizData) {
        return sendCzg(domain.concat(CzgPayEnum.JSPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgJsPayResp.class);
    }

    /**
     * 小程序支付
     *
     * @param domain    域名
     * @param appId     应用id tb_shop_merchant 表中的 app_id
     * @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
     */
    public static CzgResult<CzgLtPayResp> ltPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgLtPayReq bizData) {
        return sendCzg(domain.concat(CzgPayEnum.LTPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgLtPayResp.class);
    }

    /**
     * PC扫码支付
     *
     * @param domain    域名
     * @param appId     应用id tb_shop_merchant 表中的 app_id
     * @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
     */
    public static CzgResult<CzgScanPayResp> scanPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgScanPayReq bizData) {
        return sendCzg(domain.concat(CzgPayEnum.SCANPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgScanPayResp.class);
    }

    /**
     * 聚合反扫
     *
     * @param domain    域名
     * @param appId     应用id tb_shop_merchant 表中的 app_id
     * @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
     */
    public static CzgResult<CzgMicroPayResp> microPay(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgMicroPayReq bizData) {
        return sendCzg(domain.concat(CzgPayEnum.MICROPAY.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgMicroPayResp.class);
    }

    /**
     * 订单查询
     *
     * @param domain     域名
     * @param appId      应用id tb_shop_merchant 表中的 app_id
     * @param appSecret  应用密钥 tb_shop_merchant 表中的 app_secret
     * @param payOrderId 平台订单号
     * @param mchOrderNo 商户订单号
     */
    public static CzgResult<CzgBaseResp> queryPayOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret,
                                                       String payOrderId, String mchOrderNo) {
        JSONObject queryPayOrder = new JSONObject();
        queryPayOrder.put("payOrderId", payOrderId);
        queryPayOrder.put("mchOrderNo", mchOrderNo);
        return sendCzg(domain.concat(CzgPayEnum.TRADE.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, queryPayOrder), CzgBaseResp.class);
    }


    /**
     * 订单退款
     *
     * @param domain    域名
     * @param appId     应用id tb_shop_merchant 表中的 app_id
     * @param appSecret 应用密钥 tb_shop_merchant 表中的 app_secret
     */
    public static CzgResult<CzgRefundResp> refundOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret, CzgRefundReq bizData) {
        return sendCzg(domain.concat(CzgPayEnum.REFUND.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, bizData), CzgRefundResp.class);
    }

    /**
     * 退款订单查询
     *
     * @param domain        域名
     * @param appId         应用id tb_shop_merchant 表中的 app_id
     * @param appSecret     应用密钥 tb_shop_merchant 表中的 app_secret
     * @param mchRefundNo   商户退款订单号 二选一
     * @param refundOrderId 平台退款订单号 二选一
     */
    public static CzgResult<CzgRefundResp> queryRefundOrder(@NonNull String domain, @NonNull String appId, @NonNull String appSecret,
                                                            String mchRefundNo, String refundOrderId) {
        JSONObject queryPayOrder = new JSONObject();
        queryPayOrder.put("mchRefundNo", mchRefundNo);
        queryPayOrder.put("refundOrderId", refundOrderId);
        return sendCzg(domain.concat(CzgPayEnum.QUERY_REFUND.getUri()), CzgBaseReqParams.getInstance(appId, appSecret, queryPayOrder), CzgRefundResp.class);
    }


    /**
     * 回调数据处理
     */
    public static JSONObject getCzg(CzgBaseRespParams respParams) {
        AssertUtil.isNull(respParams, "超掌柜交易 回调数据为空");
        log.info("超掌柜交易请求响应,{}", respParams);
        if (!"000000".equals(respParams.getCode())) {
            log.error("超掌柜回调响应失败,{}", respParams);
            return null;
        }
//        if (StrUtil.isNotBlank(respParams.getSign())) {
//            if (validateSign(respParams.getSign(), respParams.getBizData())) {
//                log.error("超掌柜回调 验签失败");
//            }
//        }
        return JSONObject.parse(respParams.getBizData());

    }

    /**
     * 默认Post
     *
     * @param url    请求地址
     * @param params 参数实体
     * @return {
     * "code": "状态码",  200为成功
     * "msg": "描述"
     * "data": "返回Json数据",
     * }
     */
    private static <T> CzgResult<T> sendCzg(String url, CzgBaseReqParams params, Class<T> clazz) {
        CzgResult<T> result = CzgResult.success();
        Map<String, Object> reqMap = BeanUtil.beanToMap(params, false, false);
        params.setSign(MD5Util.md5AsHex(sortFields(new TreeMap<>(reqMap))));
        log.info("超掌柜交易请求参数,{}", JSONObject.toJSONString(params));
        try (HttpResponse resp = HttpRequest.post(url).body(JSONObject.toJSONString(params)).execute()) {
            if (resp.isOk()) {
                // 获取响应体
                String respStr = resp.body();
                if (StrUtil.isNotEmpty(respStr)) {
                    log.info("超掌柜交易请求响应元数据,{}", respStr);
                    CzgBaseRespParams respParams = JSONObject.parseObject(respStr, CzgBaseRespParams.class);
                    log.info("超掌柜交易请求响应,{}", respParams);

                    result.setCode("000000".equals(respParams.getCode()) ? 200 : Integer.parseInt(respParams.getCode()));
                    result.setMsg(respParams.getMsg());
                    if ("000000".equals(respParams.getCode()) && StrUtil.isNotBlank(respParams.getSign())) {
//                        if (validateSign(respParams.getSign(), JSONObject.toJSONString(respParams))) {
//                            result.setCode(CzgRespCode.FAILURE.getCode());
//                            result.setMsg("验签失败");
//                            log.info("验签失败");
//                        }
                        result.setData(JSONObject.parseObject(respParams.getBizData(), clazz));
                    }
                } else {
                    result.setCode(resp.getStatus());
                    result.setMsg("超掌柜交易请求失败");
                    log.error("超掌柜交易请求失败，状态码: {}", resp.getStatus());
                }
            } else {
                result.setCode(resp.getStatus());
                result.setMsg("超掌柜交易请求失败");
            }
        } catch (Exception e) {
            log.error("超掌柜交易请求异常", e);
        }
        return result;
    }

    /**
     * @param sign        签名
     * @param dataJsonStr 业务数据
     * @return false 验签通过 true 验签失败
     */
    private static boolean validateSign(String sign, String dataJsonStr) {
        Map<String, Object> dataMap = JSONObject.parseObject(dataJsonStr, new TypeReference<>() {
        });
        String newSign = MD5Util.md5AsHex(sortFields(new TreeMap<>(dataMap)));
        return !StrUtil.equals(sign, newSign);
    }

    private static String sortFields(TreeMap<String, Object> map) {
        if (CollectionUtil.isEmpty(map)) {
            log.error("超掌柜支付参数为空！！！");
            throw new RuntimeException("参数为空");
        }
        String sortParam = map.entrySet().stream()
                // 过滤掉键为 "sign" 的元素
                .filter(entry -> !"sign".equals(entry.getKey()) && !"appSecret".equals(entry.getKey()))
                // 将每个键值对转换为 "key=value" 格式的字符串
                .map(entry -> entry.getKey() + "=" + entry.getValue())
                // 使用 "&" 连接所有转换后的字符串
                .collect(Collectors.joining("&"));
        if (map.containsKey("appSecret")) {
            sortParam = sortParam.concat("&" + "appSecret=" + map.get("appSecret"));
        }
        return sortParam;
    }


//    public static void main(String[] args) {
////        String appId = "66691a6afdf641f0bf1dc701";
//        String appId = "66e3dd399a7621f45a6293c1";
////        String appSecret = "jikd52TefZcSPI5hRWrfPSpQcXZrbqshbnLmqH6UattqspIDEzjbGvZmfwTW58RMf1XuPhN4zE1GbIjKy3b1oabgOx5n79faT93Si6i7g2IPSQJAln2NNsCSNynHIJ8";
//        String appSecret = "2p7TCixkN3FuhTqJyr23GNAfrqAqUt84T1IOSunCEEqFBP9gVkSO8CqrfNwNAJqLYuWmQou7lbwdW0Lb4zJVkBEdV7CPq3VhnbGDRIpQXpBNPOjJbor1IFGuLLOA7oll";
//        CzgJsPayReq bizData = new CzgJsPayReq("20250428150248328893", 100L,
//                "订单支付", "or1l867cx6JFbLgmppwtG46AUhwg","1.80.211.145", "http://store.sxczgkj.com/h5/#/pages/user-order/user-order", "", "");
//        bizData.setCurrency("cny");
//        bizData.setPayType("WECHAT");
//        bizData.setSubAppid("wxd88fffa983758a30");
//
//        bizData.setSubject("订单支付");
////        bizData.setStoreId("S2409148611");
//        bizData.setStoreId("S2406120331");
//
//        CzgBaseReqParams params = CzgBaseReqParams.getInstance(appId, appSecret, bizData);
//        params.setVersion("1.0");
//        params.setReqId("57143686759273485473");
//        params.setReqTime("20250428150248");
//        params.setSignType("MD5");
//        CzgResult<CzgH5PayResp> czgH5PayRespCzgResult = sendCzg("https://paymentapi.sxczgkj.cn/api/open/payment/jspay", params, CzgH5PayResp.class);
//        System.out.println(czgH5PayRespCzgResult);
//    }


//    public static void main(String[] args) {
//        CzgResult<Object> result = CzgResult.success();
//        CzgBaseRespParams respParams = new CzgBaseRespParams();
//        respParams.setCode("000000");
//        respParams.setMsg("成功");
//        respParams.setSign("6c0f1e11b0d3a16298c2dfeee8c1491a");
//        respParams.setBizData("{\"amount\":500,\"currency\":\"cny\",\"ifCode\":\"lklspay\",\"mchOrderNo\":\"WX1889977729515615615\",\"mercNo\":\"B240612563201\",\"note\":\"成功\",\"payOrderId\":\"202502151890598483156443138V6W\",\"payType\":\"WECHAT\",\"settlementType\":\"D1\",\"state\":\"TRADE_SUCCESS\",\"storeId\":\"S2406125309\",\"subject\":\"超掌柜\",\"tradeFee\":2}");
//        respParams.setTimestamp("20250215110620");
//        log.info("超掌柜交易请求响应,{}", respParams);
//
//        result.setCode("000000".equals(respParams.getCode()) ? 200 : Integer.parseInt(respParams.getCode()));
//        result.setMsg(respParams.getMsg());
//        if ("000000".equals(respParams.getCode()) && StrUtil.isNotBlank(respParams.getSign())) {
//            if (validateSign(respParams.getSign(), JSONObject.toJSONString(respParams))) {
//                log.info("验签失败");
//            }
//            result.setData(JSONObject.parseObject(respParams.getBizData(), CzgMicroPayResp.class));
//        }
//        System.out.println(JSONObject.toJSONString(result));
//    }
}
