package com.crm.ucard.util;

import cn.hutool.json.JSONUtil;
import com.crm.ucard.config.UcardConfig;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author houn
 * @Date 2025/3/31 18:55
 * @PackageName:com.crm.ucard.utils
 * @ClassName: PayouCardUtil
 * @Description: TODO
 */
@Slf4j
public class PayouCardUtil {

    public static final String DATA = "data";
    public static final String SIGNATURE = "signature";
    public static final String REQUEST_ID = "requestId";
    public static final String MERCHANT_ID = "merchantId";
    public static final String PYC = "PYC";

    /**
     * Verify signature
     * @param responseStr response string
     * @return
     * @throws Exception
     */
    public static boolean verifySignature(UcardConfig config,String responseStr) throws Exception {
        Map<String, Object> requestMap = JSONUtil.toBean(responseStr, Map.class);
        String signature = String.valueOf(requestMap.get(SIGNATURE));
        requestMap.remove(SIGNATURE);

        //验证 signature
        String signDataStr = getTreeValue(requestMap);
        log.info("verify signDataStr:{}", signDataStr);
        return RsaUtils.verify(signDataStr.getBytes(StandardCharsets.UTF_8), config.getPayouCardPublicKey(), signature);
    }

    /**
     * 构建请求参数
     */
    public static Map<String, Object> buildRequestParams(UcardConfig config, Object data) {
        Map<String, Object> params = new HashMap<>();
        params.put(REQUEST_ID, generateRequestId());
        params.put(MERCHANT_ID, config.getMerchantId());
        params.put(DATA, data);
        return params;
    }

    /**
     * 生成请求ID
     */
    private static String generateRequestId() {
        return PYC + DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + RandomStringUtils.randomNumeric(3);
    }

    public static String initCommonRequest(Object data, UcardConfig ucardConfig) throws Exception {
        Map<String, Object> commonParamMap = buildCommonParam(data, ucardConfig.getMerchantId());
        String signDataStr = getTreeValue(commonParamMap);
        log.info("signDataStr:{}", signDataStr);

        commonParamMap.put("signature", RsaUtils.signSHA256(signDataStr.getBytes(StandardCharsets.UTF_8), ucardConfig.getPrivateKey()));
        String commonParamStr = JSONUtil.toJsonStr(commonParamMap);
        log.info("commonRequest:{}", commonParamStr);
        return commonParamStr;
    }

    /**
     * Construct signature string
     *
     * @param paramMap
     * @return
     */
    public static String getTreeValue(Map<String, Object> paramMap) {
        TreeMap<String, Object> params = new TreeMap<>(paramMap);
        StringBuilder origin = new StringBuilder();
        for (String key : params.keySet()) {
            Object value = params.get(key);
            String valueStr = String.valueOf(value);
            //空值参数不参与签名
            if (Objects.nonNull(value) && valueStr != null && !valueStr.equals("null") && StringUtils.isNotBlank(valueStr)) {
                origin.append("&").append(key).append("=").append(valueStr);
            }
        }
        return origin.substring(1);
    }

    private static Map<String, Object> buildCommonParam(Object data,String merchantId) {
        Map<String, Object> commonParamMap = new HashMap<>();
        commonParamMap.put(REQUEST_ID, generateRequestId());
        commonParamMap.put(MERCHANT_ID, merchantId);
        commonParamMap.put(DATA, data);
        if (Objects.nonNull(data)) {
            if (JSONUtil.isTypeJSONObject(String.valueOf(data))) {
                commonParamMap.put(DATA, JSONUtil.parseObj(data));
            } else if (JSONUtil.isTypeJSONArray(String.valueOf(data))) {
                commonParamMap.put(DATA, JSONUtil.parseArray(data));
            }
        }
        return commonParamMap;
    }
}