package com.yn.bftl.thirdparty.modules.chinaums.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yn.bftl.common.common.exception.YnceError;
import com.yn.bftl.common.common.util.RSAEncryptorUtil;
import com.yn.bftl.common.modules.configuration.entity.ThirdPartyPaySet;
import com.yn.bftl.thirdparty.common.exception.YnceErrorException;
import com.yn.bftl.thirdparty.common.util.HttpClientUtil;
import com.yn.bftl.thirdparty.modules.business.util.ThirdPartyConfigUtil;
import com.yn.bftl.thirdparty.modules.chinaums.vo.chinaums.ChinaumsResponseVO;
import com.yn.bftl.thirdparty.modules.log.service.LoggerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 * 银联工具类
 *
 * @author huabiao
 * @create 2022/12/5  17:20
 **/
@Component
@Slf4j
public class ChinaumsUtil {

    /**
     * 银联接口域名
     */
    private static String DOMAIN_NAME = null;

    /**
     * 银联公钥
     */
    private static String PUBLIC_KEY = null;

    /**
     * 银联私钥
     */
    private static String PRIVATE_KEY = null;

    /**
     * 银联商户ID
     */
    private static String MERCHANT_ID = null;

    /**
     * 银联银行编码
     */
    private static String INS_ID_CD = null;

    /**
     * 银联费用电子账簿ID
     */
    private static String CHINAUMS_FEE_BALANCE_ACCT_ID = null;

    /**
     * 配置更新时间
     */
    public static LocalDateTime updatedOn;

    /**
     * 默认支付密码
     */
    private static final String DEFAULT_PASSWORD = "123456";

    @Resource
    private ThirdPartyConfigUtil thirdPartyConfigUtil;
    @Resource
    private LoggerService loggerService;
    @Value("${spring.profiles.active}")
    private String active;

    /**
     * 配置初始化
     *
     * @return 第三方支付配置
     * @description
     * @author huabiao
     * @create 2022/9/1  15:29
     */
    public void configInit() {
        ThirdPartyPaySet thirdPartyPaySet = thirdPartyConfigUtil.getPlatform();
        if (thirdPartyPaySet == null) {
            throw new YnceErrorException(YnceError.YNCE_218001, "未配置参数");
        }
        if (StringUtils.isBlank(thirdPartyPaySet.getChinaumsDomainName())
                || StringUtils.isBlank(thirdPartyPaySet.getChinaumsPublicKey())
                || StringUtils.isBlank(thirdPartyPaySet.getChinaumsPrivateKey())
                || StringUtils.isBlank(thirdPartyPaySet.getChinaumsInsIdCd())
                || StringUtils.isBlank(thirdPartyPaySet.getChinaumsMerchantId())
                || StringUtils.isBlank(thirdPartyPaySet.getChinaumsFeeBalanceAcctId())) {
            throw new YnceErrorException(YnceError.YNCE_218001, "未配置银联参数");
        }
        if (thirdPartyPaySet.getUpdatedOn().equals(updatedOn)) {
            return;
        }
        // 更新第三方配置
        updatedOn = thirdPartyPaySet.getUpdatedOn();
        DOMAIN_NAME = thirdPartyPaySet.getChinaumsDomainName();
        PUBLIC_KEY = thirdPartyPaySet.getChinaumsPublicKey();
        PRIVATE_KEY = thirdPartyPaySet.getChinaumsPrivateKey();
        MERCHANT_ID = thirdPartyPaySet.getChinaumsMerchantId();
        INS_ID_CD = thirdPartyPaySet.getChinaumsInsIdCd();
        CHINAUMS_FEE_BALANCE_ACCT_ID = thirdPartyPaySet.getChinaumsFeeBalanceAcctId();
    }

    /**
     * @param url:请求路径
     * @param requestJson:请求参数
     * @param voClass          响应体类型
     * @return ChinaumsResponseVO
     * @author huabiao
     * @create 2022/9/6  11:22
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public <T> T execute(String url, JSONObject requestJson, Class<T> voClass) {
        configInit();
        try {
            // 清除null数据
            Iterator<Map.Entry<String, Object>> it = requestJson.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Object> next = it.next();
                if (next.getValue() == null || StringUtils.isBlank(next.getValue().toString())) {
                    it.remove();
                }
            }
            requestJson.put("insIdCd", INS_ID_CD);
            // 调用请求接口
            JSONObject jsonObject = HttpClientUtil.getInstance().setHeaderMap(buildRequestHead(requestJson)).sendPost(DOMAIN_NAME + url, requestJson);
            if (active.equals("test")) {
                log.debug("银联请求返回数据：" + jsonObject.toJSONString());
            }
            ChinaumsResponseVO chinaumsResponseVO = jsonObject.toJavaObject(ChinaumsResponseVO.class);
            if (chinaumsResponseVO.getMsgHead().getErrCode().equals("00000000")) {
                loggerService.unionpay(jsonObject.toJSONString(), requestJson, ChinaumsUtil.class.getName(), url, "chinaums");
                if (voClass == null) {
                    return null;
                } else {
                    return JSON.parseObject(chinaumsResponseVO.getMsgBody().toJSONString(), voClass);
                }
            } else {
                throw new RuntimeException(chinaumsResponseVO.getMsgHead().getErrInfo());
            }
        } catch (final Exception e) {
            loggerService.unionpay(e.getMessage(), requestJson, ChinaumsUtil.class.getName(), url, "chinaums");
            throw new YnceErrorException(YnceError.YNCE_218001, e.getMessage());
        }
    }

    /**
     * 拼接请求报文头
     *
     * @param jsonObject:请求参数集合
     * @return 请求体
     * @author huabiao
     * @create 2022/9/7  10:20
     */
    private static Map<String, String> buildRequestHead(JSONObject jsonObject) throws Exception {
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Accept", "application/json");
        headerMap.put("X-OPEN-APP-ID", MERCHANT_ID);
        // 获取请求时间
        String timestamp = String.valueOf(System.currentTimeMillis());
        headerMap.put("X-OPEN-TS", timestamp);
        // 待签名串
        StringBuilder toBeSignStr = new StringBuilder();
        toBeSignStr.append("body=[")
                .append(jsonObject)
                .append("]&X-OPEN-TS=[")
                .append(timestamp)
                .append("]");
        headerMap.put("X-OPEN-SIGN", RSAEncryptorUtil.sign(toBeSignStr.toString(), RSAEncryptorUtil.getPrivateKey(PRIVATE_KEY)));
        return headerMap;
    }

    /**
     * 获取银联公钥
     *
     * @return 银联公钥
     * @author huabiao
     * @create 2022/12/6  17:09
     */
    public String getPublicKey() {
        configInit();
        return PUBLIC_KEY;
    }

    /**
     * 获取平台分账银联电子账簿ID
     * @param companyId 企业ID
     * @return 分账电子账簿ID
     * @description
     * @author huabiao
     * @create 2022/12/12  16:46
     */
    public String getBalanceAcctId(Long companyId) {
        ThirdPartyPaySet thirdPartyPaySet = thirdPartyConfigUtil.getCompany(companyId);
        return thirdPartyPaySet != null ? thirdPartyPaySet.getChinaumsBalanceAcctId() : null;
    }

    /**
     * 获取平台费用银联电子账簿ID
     *
     * @return 费用电子账簿ID
     * @description
     * @author huabiao
     * @create 2022/12/12  16:46
     */
    public String getFeeBalanceAcctId() {
        configInit();
        return CHINAUMS_FEE_BALANCE_ACCT_ID;
    }

    /**
     * 获取企业授信还款电子账簿ID
     *
     * @param companyId 企业ID
     * @return 企业授信还款电子账簿ID
     * @description
     * @author huabiao
     * @create 2023/7/8  17:20
     */
    public String getChinaumsCreditBalanceAcctId(Long companyId) {
        ThirdPartyPaySet thirdPartyPaySet = thirdPartyConfigUtil.getCompany(companyId);
        return thirdPartyPaySet != null ? thirdPartyPaySet.getChinaumsCreditBalanceAcctId() : null;
    }


    public String getDefaultPassword() {
        return DEFAULT_PASSWORD;
    }

    public static void main(String[] args) {
        PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALjHI6tGFV2WikglPTJNt2QqISY7IchvP1/P+S43wX0fiW8NFdLW3J8cij+FG8E6ahb5j2zY2MC2nRxkaW6Sq+5x1IkOVwfdLlxLz7Hxknf2Kk6iTnpRcuPcAmy4JX+G6pRpdMjlMJO/4ZWnfiLX7l1B2EU3Dp0/Y4qQxLbxudT/AgMBAAECgYBJDIlAa9uEfUA712UDHxBSbAlg6N2pNLnUMg8rw2UeBzq5CW5IRSNBT/IjvIbFdEd+v7iA6pV+UnN4RwYbbabEV6Dd/MeFOOyG6JtptT00ZwyC191/cF41yCukLZHQascJWQcOzBirc0SWwhLH0Z3JMAwMb4Buhm9/mAvL12cdOQJBAPEU+k62dBO89g41ioYS6YigEmN1mdUn7DshvrkXFtYMEcLj3x05nTmFUdHJrtnmZlxpHFO5kyYmXzSylrXfiP0CQQDENj0qsySnYvSUyV7z/dsAR5dA1G/8GofLY+mECouzzyUCoXmdDEzLTswadal+GWfnY2WZhj7Is2lvWCHNiOSrAkAclCkMFbLy+A6PJqeyNyG6EYe8hJ9k1mO5qslqNaN+YlXkrZCwbTkHLZfCb88rg5WU1N0Hy9L2zcuxeo5FJyedAkBvaxlayPV0c7XNU3gu9yVISF70em3I68vWzDqLN23TQjqS/tzPOG/XNzyhfdUsfQLKm1/TSS8XywGBL7uqOiUXAkEAiohABeRta4XbSPLJJbBSogl5dpSzfvzbcAXxqPLpqKzQ68oNDFLO+fg7FbvXG9O8VriWAodBXoMTiFXVUFBkhA==";
        MERCHANT_ID = "wanantest";
        DOMAIN_NAME = "https://mobl-test.chinaums.com";
        INS_ID_CD = "0001000005";
        ChinaumsUtil chinaumsUtil = new ChinaumsUtil();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("outRequestNo", "123123");
        jsonObject.put("balanceAcctId", "2007279991359167556");
        jsonObject.put("freeze", "false");
        chinaumsUtil.execute("/wallet/upapi/balance_accts_freeze", jsonObject, JSONObject.class);

    }
}
