package com.cyksj.common.util;

import lombok.extern.slf4j.Slf4j;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;

/**
 * @author valor.
 * @date 2019/11/18 16:24
 */
@Slf4j
public class NSslKit {

    private NSslKit() { }

    private static class Wechat {

        private static final String certPath = "cert/apiclient_cert.p12";
        private static final String password = "1634772026";
        private static final String certType = "PKCS12";

        private static final SSLContext sslContext;
        static {
            sslContext = wechatRefundSSL();
        }

        private static final HostnameVerifier verifier;
        static {
            verifier = ((s, sslSession) -> true);
        }

        private static SSLContext wechatRefundSSL() {
            try {
                char[] pass = Wechat.password.toCharArray();

                // 读取客户端证书
                KeyStore keyStore = getKeyStore(Wechat.certPath, pass, Wechat.certType);
                // 双向认证  客户端需要向服务端提交证书
                KeyManager[] keyManagers = keyManagers(keyStore, pass);
                // 由于微信退款证书 是自签名证书 不通过ca认证 则忽略证书校验
                TrustManager[] trustManagers = trustManagers();

                SSLContext ctx = SSLContext.getInstance("TLS");
                ctx.init(keyManagers, trustManagers, null);

                return ctx;
            } catch (Throwable e) {
                log.info("微信退款证书读取错误: \n{}", e.getMessage());
                throw new RuntimeException(e);
            }
        }
    }

    public enum KeyCert {
        wechat_refund(Wechat.sslContext, Wechat.verifier),
        ;

        private SSLContext sslContext;
        private HostnameVerifier verifier;

        KeyCert(SSLContext ssl, HostnameVerifier verifier) {
            this.sslContext = ssl;
            this.verifier = verifier;
        }

        public SSLContext getSslContext() {
            return this.sslContext;
        }

        public HostnameVerifier getVerifier() {
            return this.verifier;
        }
    }

    /**
     * 读取本地客户端证书
     */
    private static KeyStore getKeyStore(String filepath, char[] password, String type) throws Exception {
        if (StringUtil.isBlank(filepath)) {
            throw new IllegalArgumentException("Unable to recognize key-store file.");
        }
        File file = new File(filepath);
        if (!file.exists()) {
            throw new IllegalArgumentException("Unable to recognize key-store file.");
        }

        KeyStore keyStore = KeyStore.getInstance(type);
        InputStream in = new FileInputStream(file);
        keyStore.load(in, password);
        IoKit.close(in);
        return keyStore;
    }

    /**
     * 双向认证  客户端需要向服务端提交证书
     */
    private static KeyManager[] keyManagers(KeyStore keyStore, char[] password) throws Exception {
        // 用于上传客户端证书
        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keyStore, password);
        return kmf.getKeyManagers();
    }

    /**
     * 客户端不需要向服务端提交证书
     */
    private static KeyManager[] keyManagers() {
        return null;
    }

    /**
     * 忽略证书校验
     */
    private static TrustManager[] trustManagers() throws Exception {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init((KeyStore) null);
        return tmf.getTrustManagers();
    }

    /**
     * 信任指定证书
     */
    private static TrustManager[] trustManagers(KeyStore keyStore) throws Exception {
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(keyStore);
        return tmf.getTrustManagers();
    }

    /**
     * 验证系统默认证书
     */
    private static TrustManager[] sysDefaultTrusts() {
        return null;
    }


}
