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.HttpHeaders;
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.nio.charset.StandardCharsets;
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 响应结果
     */
    /**
     * 测试环境专用：跳过SSL证书验证调用HTTPS POST请求
     * @param url HTTPS请求地址
     * @param jsonParam JSON格式的请求体
     * @return 服务端响应字符串
     * @throws RuntimeException 请求异常
     */
    public static String doPostSkipSslVerify(String url, String jsonParam) {
        // 1. 创建信任所有证书的SSL上下文
        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)
//                        .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                        .build())
                .build()) {

            // 4. 构建POST请求
            HttpPost httpPost = new HttpPost(url);
            // 设置核心请求头
            httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
            httpPost.setHeader(HttpHeaders.ACCEPT, "application/json");
            // 设置请求体（确保UTF-8编码）
            StringEntity requestEntity = new StringEntity(jsonParam, StandardCharsets.UTF_8);
            httpPost.setEntity(requestEntity);

            // 5. 执行请求并处理响应
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
//                int statusCode = response.getStatusLine().getStatusCode();
//                // 非200状态码抛出异常（便于排查）
//                if (statusCode != HttpStatus.SC_OK) {
//                    String errorResponse = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
//                    throw new RuntimeException(String.format("请求失败，状态码：%d，响应内容：%s", statusCode, errorResponse));
//                }
                HttpEntity responseEntity = response.getEntity();
                return responseEntity != null ? EntityUtils.toString(responseEntity, StandardCharsets.UTF_8) : null;
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException("发送HTTPS POST请求失败", e);
        }
    }

    /**
     * 场景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;
    }




    /**
     * 生产环境专用：合法验证SSL证书调用HTTPS POST请求
     * @param url HTTPS请求地址
     * @param jsonParam JSON格式的请求体
     * @return 服务端响应字符串
     * @throws RuntimeException 请求异常
     */
    public static String doPostProduction(String url, String jsonParam) {
        // 无需自定义SSLContext，使用默认的即可（自动验证证书）
        try (CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(PoolingHttpClientConnectionManagerBuilder.create().build())
                .setDefaultRequestConfig(RequestConfig.custom()
//                        .setConnectTimeout(CONNECT_TIMEOUT)
//                        .setResponseTimeout(READ_TIMEOUT)
//                        .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                        .build())
                .build()) {

            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
            httpPost.setHeader(HttpHeaders.ACCEPT, "application/json");
            StringEntity requestEntity = new StringEntity(jsonParam, StandardCharsets.UTF_8);
            httpPost.setEntity(requestEntity);

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
//                int statusCode = response.getStatusLine().getStatusCode();
//                if (statusCode != HttpStatus.SC_OK) {
//                    String errorResponse = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
//                    throw new RuntimeException(String.format("请求失败，状态码：%d，响应内容：%s", statusCode, errorResponse));
//                }
                HttpEntity responseEntity = response.getEntity();
                return responseEntity != null ? EntityUtils.toString(responseEntity, StandardCharsets.UTF_8) : null;
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
        } catch (IOException e) {
            throw new RuntimeException("发送HTTPS POST请求失败", e);
        }
    }
}