package com.nbport.zgwl.seal.utils;

import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.UUID;

/**
 * 签章平台HTTP客户端工具类
 *
 * @author xiaofengzhou
 */
public class SealHttpClient {

    private static final Logger log = LoggerFactory.getLogger(SealHttpClient.class);

    private static final int CONNECT_TIMEOUT = 30000;

    private static final int READ_TIMEOUT = 60000;

    public static String post(String url, String jsonBody, String accessToken, String contentType) {
        HttpURLConnection conn = null;
        try {
            conn = createConnection(url);
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("Content-Type", contentType);
            conn.setRequestProperty("Accept", "application/json");
            if (StrUtil.isNotBlank(accessToken)) {
                conn.setRequestProperty("access_token", accessToken);
            }
            conn.setRequestProperty("User-Agent", "Mozilla/5.0");

            if (jsonBody != null && !jsonBody.isEmpty()) {
                try (OutputStream os = conn.getOutputStream()) {
                    byte[] input = jsonBody.getBytes(StandardCharsets.UTF_8);
                    os.write(input, 0, input.length);
                }
            }

            return readResponse(conn);
        } catch (Exception e) {
            log.error("HTTP POST请求失败, URL: {}", url, e);
            throw new RuntimeException("请求签章平台失败: " + e.getMessage(), e);
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    public static String postMultipart(String url, MultipartFile file, String contractName, String description, String accessToken) {
        HttpURLConnection conn = null;
        String boundary = "----WebKitFormBoundary" + UUID.randomUUID().toString().replace("-", "");

        try {
            conn = createConnection(url);
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            if (StrUtil.isNotBlank(accessToken)) {
                conn.setRequestProperty("access_token", accessToken);
            }
            conn.setRequestProperty("User-Agent", "Mozilla/5.0");

            try (OutputStream os = conn.getOutputStream();
                 PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true)) {
                addFormField(writer, boundary, "contractName", contractName);

                if (description != null && !description.isEmpty()) {
                    addFormField(writer, boundary, "description", description);
                }

                writer.append("--").append(boundary).append("\r\n");
                writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"")
                        .append(file.getOriginalFilename()).append("\"\r\n");
                writer.append("Content-Type: ").append(file.getContentType()).append("\r\n\r\n");
                writer.flush();
                os.write(file.getBytes());
                os.flush();
                writer.append("\r\n");

                writer.append("--").append(boundary).append("--\r\n");
                writer.flush();
            }

            return readResponse(conn);
        } catch (Exception e) {
            log.error("文件上传请求失败, URL: {}", url, e);
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    private static void addFormField(PrintWriter writer, String boundary, String name, String value) {
        writer.append("--").append(boundary).append("\r\n");
        writer.append("Content-Disposition: form-data; name=\"")
                .append(name).append("\"\r\n\r\n");
        writer.append(value).append("\r\n");
        writer.flush();
    }

    private static HttpURLConnection createConnection(String urlStr) throws Exception {
        URL url = new URL(urlStr);
        HttpURLConnection conn;

        if ("https".equalsIgnoreCase(url.getProtocol())) {
            HttpsURLConnection httpsConn = (HttpsURLConnection) url.openConnection();
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{new TrustAllManager()}, new java.security.SecureRandom());
            httpsConn.setSSLSocketFactory(sslContext.getSocketFactory());
            httpsConn.setHostnameVerifier((hostname, session) -> true);
            conn = httpsConn;
        } else {
            conn = (HttpURLConnection) url.openConnection();
        }

        conn.setConnectTimeout(CONNECT_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);
        return conn;
    }

    private static String readResponse(HttpURLConnection conn) throws IOException {
        int responseCode = conn.getResponseCode();
        InputStream inputStream = responseCode >= 200 && responseCode < 300 ? conn.getInputStream() : conn.getErrorStream();

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

        StringBuilder response = new StringBuilder();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
        }

        log.debug("签章平台响应 [{}]: {}", responseCode, response);
        return response.toString();
    }

    private static class TrustAllManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
}
