package com.zjsgfa.framework.util;

import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Spring Boot HTTPS POST 请求工具类（管理 SSL 证书验证）
 */
public class HttpsPostUtil {

    // 超时时间配置（单位：毫秒）
    private static final int CONNECT_TIMEOUT = 5000;
    private static final int READ_TIMEOUT = 5000;

    /**
     * 场景1：跳过 SSL 证书验证（测试环境使用）
     * @param url 请求地址
     * @param jsonParam 请求体（JSON 字符串）
     * @return 响应结果
     */
    public static String doPostWithoutSslVerify(String url, String jsonParam) {
        // 1. 创建忽略证书验证的 SSLContext
        SSLContext sslContext;
        try {
            sslContext = SSLContexts.custom()
                    // 信任所有证书
                    .loadTrustMaterial((TrustStrategy) (chain, authType) -> true)
                    .build();
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            throw new RuntimeException("创建 SSL 上下文失败", e);
        }

        // 2. 创建 SSL 连接工厂（忽略主机名验证）
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                NoopHostnameVerifier.INSTANCE // 忽略主机名与证书的匹配验证
        );

        // 3. 构建 HttpClient
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
                        .setSSLSocketFactory(sslSocketFactory)
                        .build())
                .setDefaultRequestConfig(RequestConfig.custom()
//                        .setConnectTimeout(CONNECT_TIMEOUT)
//                        .setResponseTimeout(READ_TIMEOUT)
                        .build())
                .build()) {

            // 4. 构建 POST 请求
            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            // 设置请求体
            StringEntity entity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);

            // 5. 执行请求
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity responseEntity = response.getEntity();
                if (responseEntity != null) {
                    return EntityUtils.toString(responseEntity, "UTF-8");
                }
            } catch (ParseException e) {
                throw new RuntimeException("解析响应结果失败", e);
            }
        } catch (IOException e) {
            throw new RuntimeException("发送 HTTPS POST 请求失败", e);
        }
        return null;
    }

    /**
     * 场景2：加载自定义 SSL 证书（生产环境使用）
     * @param url 请求地址
     * @param jsonParam 请求体（JSON 字符串）
     * @param certPath 证书文件路径（如 .jks/.p12 格式）
     * @param certPassword 证书密码
     * @return 响应结果
     */
    public static String doPostWithCustomCert(String url, String jsonParam, String certPath, String certPassword) {
        // 1. 加载自定义证书到 KeyStore
        KeyStore keyStore;
        try {
            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
            try (FileInputStream instream = new FileInputStream(new File(certPath))) {
                keyStore.load(instream, certPassword.toCharArray());
            }
        } catch (Exception e) {
            throw new RuntimeException("加载证书失败", e);
        }

        // 2. 创建自定义 SSLContext
        SSLContext sslContext;
        try {
            sslContext = SSLContexts.custom()
                    .loadTrustMaterial(keyStore, (X509Certificate[] chain, String authType) -> {
                        // 自定义证书验证逻辑（默认信任该证书库中的证书）
                        return true;
                    })
                    .build();
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            throw new RuntimeException("创建 SSL 上下文失败", e);
        }

        // 3. 构建 SSL 连接工厂
        SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);

        // 4. 构建 HttpClient 并执行请求（逻辑同场景1）
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create()
                        .setSSLSocketFactory(sslSocketFactory)
                        .build())
                .setDefaultRequestConfig(RequestConfig.custom()
//                        .setConnectTimeout(CONNECT_TIMEOUT)
//                        .setResponseTimeout(READ_TIMEOUT)
                        .build())
                .build()) {

            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            StringEntity entity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity responseEntity = response.getEntity();
                if (responseEntity != null) {
                    return EntityUtils.toString(responseEntity, "UTF-8");
                }
            } catch (ParseException e) {
                throw new RuntimeException("解析响应结果失败", e);
            }
        } catch (IOException e) {
            throw new RuntimeException("发送 HTTPS POST 请求失败", e);
        }
        return null;
    }

    // 测试示例
    public static void main(String[] args) {
        // 场景1测试：跳过证书验证发送 POST 请求
        String testUrl = "https://localhost:8443/api/test";
        String testParam = "{\"name\":\"test\",\"age\":18}";
        String result1 = doPostWithoutSslVerify(testUrl, testParam);
        System.out.println("跳过证书验证的响应结果：" + result1);

        // 场景2测试：使用自定义证书发送 POST 请求
        // String result2 = doPostWithCustomCert(testUrl, testParam, "D:/cert/test.jks", "123456");
        // System.out.println("自定义证书的响应结果：" + result2);
    }
}