package com.bonus.common.core.utils.http;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.StringJoiner;

public class HttpRequestHelper {

    // 连接超时设置：5秒
    private static final int CONNECT_TIMEOUT = 50000;
    // 读取超时设置：5秒
    private static final int READ_TIMEOUT = 50000;

    /**
     * 发送HTTP请求的通用方法
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param method   请求方法 (GET, POST, PUT, DELETE, PATCH)
     * @param body     请求体（适用于POST、PUT、PATCH）
     * @param headers  请求头
     * @return String 响应内容
     */
    private static String sendRequest(String baseUrl, String endpoint, String method, String body, Map<String, String> headers) {
        HttpURLConnection connection = null;
        try {
            // 创建URL对象并打开连接
            URL url = new URL(baseUrl + endpoint);
            connection = (HttpURLConnection) url.openConnection();

            // 设置请求方法
            connection.setRequestMethod(method);

            // 设置连接超时和读取超时时间
            connection.setConnectTimeout(CONNECT_TIMEOUT);
            connection.setReadTimeout(READ_TIMEOUT);

            // 设置请求头
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    connection.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }

            // 如果请求体不为空，且方法是POST、PUT或PATCH，则写入请求体
            if (body != null && !body.isEmpty() && (method.equals("POST") || method.equals("PUT") || method.equals("PATCH"))) {
                connection.setDoOutput(true);
                try (OutputStream os = connection.getOutputStream()) {
                    os.write(body.getBytes());
                    os.flush();
                }
            }

            // 连接服务器并检查响应代码
            int responseCode = connection.getResponseCode();
            if (responseCode != HttpURLConnection.HTTP_OK) {
                throw new RuntimeException("Request failed with response code: " + responseCode);
            }

            // 获取输入流并读取响应内容
            StringBuilder response = new StringBuilder();
            try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    response.append(inputLine);
                }
            }

            return response.toString();

        } catch (Exception e) {
            e.printStackTrace();
            return null;

        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * 将表单数据转换为application/x-www-form-urlencoded格式的方法
     *
     * @param formData 表单数据
     * @return String 表单数据的URL编码格式
     */
    private static String getFormBody(Map<String, String> formData) {
        try {
            StringJoiner sj = new StringJoiner("&");
            for (Map.Entry<String, String> entry : formData.entrySet()) {
                sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
            }
            return sj.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 发送GET请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String get(String baseUrl, String endpoint, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "GET", null, headers);
    }

    /**
     * 发送POST请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param body     请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String post(String baseUrl, String endpoint, String body, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "POST", body, headers);
    }

    /**
     * 发送POST表单请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param formData 表单数据
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String postForm(String baseUrl, String endpoint, Map<String, String> formData, Map<String, String> headers) {
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        String formBody = getFormBody(formData);
        return sendRequest(baseUrl, endpoint, "POST", formBody, headers);
    }

    /**
     * 发送POST JSON请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param jsonBody JSON格式的请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String postJson(String baseUrl, String endpoint, String jsonBody, Map<String, String> headers) {
        headers.put("Content-Type", "application/json");
        return sendRequest(baseUrl, endpoint, "POST", jsonBody, headers);
    }

    /**
     * 发送POST XML请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param xmlBody  XML格式的请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String postXml(String baseUrl, String endpoint, String xmlBody, Map<String, String> headers) {
        headers.put("Content-Type", "application/xml");
        return sendRequest(baseUrl, endpoint, "POST", xmlBody, headers);
    }

    /**
     * 发送POST原始数据请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param rawBody  原始请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String postRaw(String baseUrl, String endpoint, String rawBody, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "POST", rawBody, headers);
    }

    /**
     * 发送PUT请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param body     请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String put(String baseUrl, String endpoint, String body, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "PUT", body, headers);
    }

    /**
     * 发送PUT表单请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param formData 表单数据
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String putForm(String baseUrl, String endpoint, Map<String, String> formData, Map<String, String> headers) {
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        String formBody = getFormBody(formData);
        return sendRequest(baseUrl, endpoint, "PUT", formBody, headers);
    }

    /**
     * 发送PUT JSON请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param jsonBody JSON格式的请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String putJson(String baseUrl, String endpoint, String jsonBody, Map<String, String> headers) {
        headers.put("Content-Type", "application/json");
        return sendRequest(baseUrl, endpoint, "PUT", jsonBody, headers);
    }

    /**
     * 发送PUT XML请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param xmlBody  XML格式的请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String putXml(String baseUrl, String endpoint, String xmlBody, Map<String, String> headers) {
        headers.put("Content-Type", "application/xml");
        return sendRequest(baseUrl, endpoint, "PUT", xmlBody, headers);
    }

    /**
     * 发送PUT原始数据请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param rawBody  原始请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String putRaw(String baseUrl, String endpoint, String rawBody, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "PUT", rawBody, headers);
    }

    /**
     * 发送DELETE请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String delete(String baseUrl, String endpoint, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "DELETE", null, headers);
    }

    /**
     * 发送PATCH请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param body     请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String patch(String baseUrl, String endpoint, String body, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "PATCH", body, headers);
    }

    /**
     * 发送PATCH表单请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param formData 表单数据
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String patchForm(String baseUrl, String endpoint, Map<String, String> formData, Map<String, String> headers) {
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        String formBody = getFormBody(formData);
        return sendRequest(baseUrl, endpoint, "PATCH", formBody, headers);
    }

    /**
     * 发送PATCH JSON请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param jsonBody JSON格式的请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String patchJson(String baseUrl, String endpoint, String jsonBody, Map<String, String> headers) {
        headers.put("Content-Type", "application/json");
        return sendRequest(baseUrl, endpoint, "PATCH", jsonBody, headers);
    }

    /**
     * 发送PATCH XML请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param xmlBody  XML格式的请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String patchXml(String baseUrl, String endpoint, String xmlBody, Map<String, String> headers) {
        headers.put("Content-Type", "application/xml");
        return sendRequest(baseUrl, endpoint, "PATCH", xmlBody, headers);
    }

    /**
     * 发送PATCH原始数据请求
     *
     * @param baseUrl  基URL
     * @param endpoint 请求的端点
     * @param rawBody  原始请求体
     * @param headers  请求头
     * @return String 响应内容
     */
    public static String patchRaw(String baseUrl, String endpoint, String rawBody, Map<String, String> headers) {
        return sendRequest(baseUrl, endpoint, "PATCH", rawBody, headers);
    }
}
