package com.liquidnet.service.dragon.utils;

import com.alipay.api.internal.util.file.IOUtils;
import com.liquidnet.commons.lang.util.MD5Utils;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.*;

public class PayDouYinpayUtils {
    private CloseableHttpClient httpClient;
    private static PayDouYinpayUtils instance = new PayDouYinpayUtils();

    // 池化管理
    private static PoolingHttpClientConnectionManager poolConnManager =null;

    private final String merchantId = "1551961491";
    private final String partnerKey = "itIuO65O9yKmemOu3S8g1S4orqvCGwXK";
    private final String SALT = "D3rXySlTCR15LxYnmbEOaamGoOCbBNQAbFtaK39t";


    private final String APP_ID="tt0d647bd9925c076801";



    public PayDouYinpayUtils() {
    }

    public static PayDouYinpayUtils getInstance() {
        return instance;
    }


    public String getAPP_ID() {
        return APP_ID;
    }


    public String getMerchantId() {
        return merchantId;
    }



    public CloseableHttpClient getHttpClient() {
        try {
            if (httpClient == null) {

                InputStream certStream = PayDouYinpayUtils.class.getClassLoader().getResourceAsStream("payCert/wepay/wepay_apiclient_cert.p12");
                byte[] certData = IOUtils.toByteArray(certStream);
                certStream.read(certData);
                certStream.close();

                KeyStore keyStore = KeyStore.getInstance("PKCS12");
                ByteArrayInputStream inputStream = new ByteArrayInputStream(certData);
                try {
                    keyStore.load(inputStream, merchantId.toCharArray());
                } finally {
                    inputStream.close();
                }
                SSLContext sslcontext = SSLContexts.custom()
                        .loadKeyMaterial(keyStore, merchantId.toCharArray())
                        .build();
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslcontext,
                        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

                // 配置同时支持 HTTP 和 HTPPS
                Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build();
                // 初始化连接管理器
                poolConnManager =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
                poolConnManager.setMaxTotal(4000);// 同时最多连接数
                // 设置最大路由
                poolConnManager.setDefaultMaxPerRoute(2000);

                // 初始化httpClient
                httpClient = getConnection();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpClient;
    }

    public static CloseableHttpClient getConnection() {
        RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(5000).build();
        CloseableHttpClient httpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(poolConnManager)
                .setDefaultRequestConfig(config)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(2,false)).build();
        return httpClient;
    }

    //生成随机字符串nonce_str
    public String getNonceStr() {
        String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < 32; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public String createSign(SortedMap<String, Object> paramsMap) {
        List<String> paramsArr = new ArrayList<>();
        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            String key = entry.getKey();
            if (key.equals("other_settle_params")) {
                continue;
            }
            String value = entry.getValue().toString();

            value = value.trim();
            if (value.startsWith("\"") && value.endsWith("\"") && value.length() > 1) {
                value = value.substring(1, value.length() - 1);
            }
            value = value.trim();
            if (value.equals("") || value.equals("null")) {
                continue;
            }
            switch (key) {
                case "app_id":
                case "thirdparty_id":
                case "sign":
                    break;
                default:
                    paramsArr.add(value);
                    break;
            }
        }
        paramsArr.add(SALT);
        Collections.sort(paramsArr);
        StringBuilder signStr = new StringBuilder();
        String sep = "";
        for (String s : paramsArr) {
            signStr.append(sep).append(s);
            sep = "&";
        }
        return md5FromStr(signStr.toString());
    }
    public static String md5FromStr(String inStr) {
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "";
        }

        byte[] byteArray = inStr.getBytes(StandardCharsets.UTF_8);
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuilder hexValue = new StringBuilder();
        for (byte md5Byte : md5Bytes) {
            int val = ((int) md5Byte) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }
            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

    public String getPartnerKey() {
        return this.partnerKey;
    }

    public boolean notifySign(Map<String, String> result, String sign) {
        String argNotifySign = getStringByStringMap(result) + "&key=" + this.partnerKey;
        String notifySign = MD5Utils.md5(argNotifySign).toUpperCase();
        if (notifySign.equals(sign)) {
            return true;
        } else {
            return false;
        }
    }

    public static String getStringByStringMap(Map<String, String> map) {
        SortedMap<String, Object> smap = new TreeMap<String, Object>(map);
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, Object> m : smap.entrySet()) {
            sb.append(m.getKey()).append("=").append(m.getValue()).append("&");
        }
        sb.delete(sb.length() - 1, sb.length());
        return sb.toString();
    }

    public static void main(String[] args) {
        SortedMap<String, Object> paramMap = new TreeMap<String, Object>();
        paramMap.put("appid", "wx86f9777acf2cb585");
        paramMap.put("partnerid", "1551961491");
        paramMap.put("prepayid", "wx26131443671359787bb3996a1fa0fc0000");
        paramMap.put("package", "Sign=WXPay");
        paramMap.put("noncestr", "rGcsOnNdZ4d9zu6k3yCbVJRG8Ombp8VW");
        paramMap.put("timestamp", "1627276483");
        String sign = PayDouYinpayUtils.getInstance().createSign(paramMap);
        System.out.println("1627274771===="+sign);
    }
}
