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.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
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 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";

    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 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;
    }

    //生成随机字符串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 static boolean notifySign(Map<String, String> result, String sign, String partnerKey) {
        String argNotifySign = getStringByStringMap(result) + "&key=" + 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();
    }
}
