package com.agri.api.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * HTTP JSON调用工具类（JDK 8原生实现，支持调用三方接口）
 */
public class HttpJsonUtil {
    private static final Logger log = LoggerFactory.getLogger(HttpJsonUtil.class);
    // JSON序列化/反序列化工具（需引入jackson依赖）
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    // 默认超时时间（毫秒）
    private static final int DEFAULT_CONNECT_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(10);
    private static final int DEFAULT_READ_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);

    /**
     * POST JSON请求（最常用）
     * @param url 三方接口地址
     * @param requestBody 请求体（Java对象，自动转为JSON）
     * @param headers 请求头（如token、Content-Type等）
     * @param responseType 响应结果类型
     * @return 解析后的响应对象
     */
    public static <T> T doPostJson(String url, Object requestBody, Map<String, String> headers, Class<T> responseType) {
        try {
            // 1. 构建连接
            HttpURLConnection conn = getHttpURLConnection(url, "POST");
            // 2. 设置请求头
            setHeaders(conn, headers);
            // 3. 写入JSON请求体
            writeRequestBody(conn, requestBody);
            // 4. 获取响应
            return getResponse(conn, responseType);
        } catch (Exception e) {
            log.error("POST JSON请求失败，url={}", url, e);
            throw new RuntimeException("调用三方接口失败：" + e.getMessage());
        }
    }

    /**
     * GET请求（无请求体，参数拼在URL后）
     * @param url 三方接口地址（含参数，如http://xxx/api?name=test）
     * @param headers 请求头
     * @param responseType 响应结果类型
     * @return 解析后的响应对象
     */
    public static <T> T doGet(String url, Map<String, String> headers, Class<T> responseType) {
        try {
            // 1. 构建连接
            HttpURLConnection conn = getHttpURLConnection(url, "GET");
            // 2. 设置请求头
            setHeaders(conn, headers);
            // 3. 获取响应
            return getResponse(conn, responseType);
        } catch (Exception e) {
            log.error("GET请求失败，url={}", url, e);
            throw new RuntimeException("调用三方接口失败：" + e.getMessage());
        }
    }

    /**
     * 构建HTTP连接
     */
    private static HttpURLConnection getHttpURLConnection(String url, String method) throws IOException {
        URL apiUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) apiUrl.openConnection();
        // 设置请求方法
        conn.setRequestMethod(method);
        // 允许输入输出（POST需要）
        conn.setDoInput(true);
        conn.setDoOutput(true);
        // 设置超时
        conn.setConnectTimeout(DEFAULT_CONNECT_TIMEOUT);
        conn.setReadTimeout(DEFAULT_READ_TIMEOUT);
        // 禁用缓存
        conn.setUseCaches(false);
        return conn;
    }

    /**
     * 设置请求头
     */
    private static void setHeaders(HttpURLConnection conn, Map<String, String> headers) {
        // 默认Content-Type
        conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
        conn.setRequestProperty("Accept", "application/json");
        // 自定义请求头
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 写入JSON请求体
     */
    private static void writeRequestBody(HttpURLConnection conn, Object requestBody) throws IOException {
        if (requestBody == null) {
            return;
        }
        try (OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8)) {
            // 将Java对象转为JSON字符串
            String jsonBody = OBJECT_MAPPER.writeValueAsString(requestBody);
            log.debug("HTTP请求体：{}", jsonBody);
            writer.write(jsonBody);
            writer.flush();
        }
    }

    /**
     * 获取并解析响应
     */
    private static <T> T getResponse(HttpURLConnection conn, Class<T> responseType) throws IOException {
        int responseCode = conn.getResponseCode();
        // 处理成功响应（200-299）
        if (responseCode >= 200 && responseCode < 300) {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
                StringBuilder responseStr = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    responseStr.append(line);
                }
                log.debug("HTTP响应结果：{}", responseStr);
                // 将JSON字符串转为Java对象
                return OBJECT_MAPPER.readValue(responseStr.toString(), responseType);
            }
        } else {
            // 处理错误响应
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getErrorStream(), StandardCharsets.UTF_8))) {
                StringBuilder errorStr = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    errorStr.append(line);
                }
                log.error("HTTP请求错误，响应码={}，错误信息={}", responseCode, errorStr);
                throw new RuntimeException("三方接口返回错误：响应码=" + responseCode + "，信息=" + errorStr);
            }
        }
    }

    // 重载方法：无自定义请求头的POST
    public static <T> T doPostJson(String url, Object requestBody, Class<T> responseType) {
        return doPostJson(url, requestBody, null, responseType);
    }

    // 重载方法：无自定义请求头的GET
    public static <T> T doGet(String url, Class<T> responseType) {
        return doGet(url, null, responseType);
    }
}