package com.liquidnet.service.dragon.utils;

import com.alipay.api.internal.util.file.IOUtils;
import com.liquidnet.commons.lang.util.MD5Utils;
import org.apache.commons.lang3.StringUtils;
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.security.KeyStore;
import java.security.Security;
import java.util.*;

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

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

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

    private final String APP_ID = "wx86f9777acf2cb585";
    private final String WEB_APP_ID = "wx3498304dda39c5a1";
    private final String JS_APP_ID = "wx3498304dda39c5a1";
    private final String WAP_APP_ID = "wx3498304dda39c5a1";
    private final String APPLET_APP_ID = "wx4732efeaa2b08086";
    private final String APPLETB_APPID="wxe3a093ce7278d5b1";
    private final String merchantBId="1614003616";

    public PayWepayUtils() {
    }

    public static PayWepayUtils getInstance() {
        return instance;
    }


    public String getAPP_ID() {
        return APP_ID;
    }

    public String getAPPLET_APP_ID() {
        return APPLET_APP_ID;
    }

    public String getJS_APP_ID() {
        return JS_APP_ID;
    }

    public String getWEB_APP_ID() {
        return WEB_APP_ID;
    }

    public String getWAP_APP_ID() {
        return WAP_APP_ID;
    }

    public String getMerchantId() {
        return merchantId;
    }

    public String getAPPLETB_APPID() {
        return APPLETB_APPID;
    }

    public String getMerchantBId() {
        return merchantBId;
    }

//    public CloseableHttpClient getHttpClient() {
//        try {
//            if (httpClient == null) {
//                InputStream certStream = PayWepayUtils.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());
//                httpClient = HttpClients.custom()
//                        .setSSLSocketFactory(sslsf)
//                        .build();
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return httpClient;
//    }

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

                InputStream certStream = PayWepayUtils.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> parameters) {
        StringBuffer sb = new StringBuffer();
        Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序（升序）
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            Object v = entry.getValue();
            if (null != v && !"".equals(v)
                    && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + partnerKey);
        return MD5Utils.md5(sb.toString()).toUpperCase();
    }

    public String getRequestXml(SortedMap<String, Object> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set es = parameters.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) {
                sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
            } else {
                sb.append("<" + k + ">" + v + "</" + k + ">");
            }
        }
        sb.append("</xml>");
        return sb.toString();
    }

    public String unCodeReqInfo(String reqInfo) {
        try {
            Cipher cipher;
            String key = MD5Utils.md5(partnerKey);
            SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
            Security.addProvider(new BouncyCastleProvider());

            cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

            Base64.Decoder decoder = Base64.getDecoder();
            byte[] base64ByteArr = decoder.decode(reqInfo);
            String result = new String(cipher.doFinal(base64ByteArr));
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    @SuppressWarnings("unchecked")
    public static Map<String, String> parseXml(InputStream inputStream) throws Exception {

        if (inputStream == null) {
            return null;
        }

        Map<String, String> map = new HashMap<String, String>();// 将解析结果存储在HashMap中
        SAXReader reader = new SAXReader();// 读取输入流
        Document document = reader.read(inputStream);
        Element root = document.getRootElement();// 得到xml根元素
        List<Element> elementList = root.elements();// 得到根元素的所有子节点
        for (Element e : elementList) { // 遍历所有子节点
            map.put(e.getName(), e.getText());
        }

        inputStream.close(); // 释放资源
        inputStream = null;

        return map;
    }

    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()) {
            if (null != m.getValue()) {
                if (StringUtils.isNotBlank(m.getValue().toString())) {
                    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 = PayWepayUtils.getInstance().createSign(paramMap);
        System.out.println("1627274771====" + sign);
    }
}
