package com.ruoyi.common.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.enums.DataType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * http请求--该工具类只适用于报表设计-rest接口数据源
 */
public class HttpRequestUtil {

    private final static Logger LOGGER = LoggerFactory.getLogger(HttpRequestUtil.class);

    /**
     * 发送请求查询数据
     *
     * @param requestUrl    请求路径
     * @param requestMethod 请求方式
     * @param requestBody   请求体
     * @param requestHeader 请求头
     * @return 响应结果
     * @throws IOException 异常
     */
    public static String getDataByRequest(String requestUrl, String requestMethod, Map<String, String> requestHeader, String requestBody) throws IOException {
        LOGGER.info(">> 访问接口：\n请求地址：{}\n请求方式：{}\n请求头：{}\n请求参数：{}", requestUrl, requestMethod, requestHeader != null ? JSON.toJSON(requestHeader) : "", requestBody);
        String result;
        BufferedReader in = null;
        DataOutputStream out = null;
        if ("GET".equalsIgnoreCase(requestMethod) && !StringUtils.isEmpty(requestBody)) {
            Map<String, Object> bodyMap = JsonUtils.jsonToPojo(requestBody, Map.class);
            StringBuilder urlSb = new StringBuilder(requestUrl).append("?");
            for (String key : bodyMap.keySet()) {
                urlSb.append(key).append("=").append(bodyMap.get(key)).append("&");
            }
            urlSb.deleteCharAt(urlSb.length() - 1);
            requestUrl = urlSb.toString().replaceAll(" ", "%20");
        }
        HttpURLConnection conn = getHttpConnection(requestUrl, requestMethod);
        try {
            if (!"GET".equalsIgnoreCase(requestMethod) && !StringUtils.isEmpty(requestBody)) {
                conn.setDoInput(true);
                conn.setDoOutput(true);
                if (requestHeader != null && !requestHeader.isEmpty()) {
                    requestHeader.forEach(conn::setRequestProperty);
                }
                out = new DataOutputStream(conn.getOutputStream());
                out.writeBytes(requestBody);
            }
            conn.connect();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String temp;
            while ((temp = in.readLine()) != null) {
                sb.append(temp).append(" ");
            }
            result = sb.toString();
            LOGGER.info(">> 访问结果：{}", result);
            return result;
        } catch (IOException ex) {
            LOGGER.error(">> 访问接口失败：{}", ex.getMessage(), ex);
        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.flush();
                out.close();
            }
        }
        return null;
    }

    public static JSONObject getRequest(String requestUrl) {
        return getRequest(requestUrl, null);
    }

    public static JSONObject getRequest(String requestUrl, Map<String, Object> requestBody) {
        return getJSONObjectByRequest(requestUrl, "GET", null, requestBody != null ? JsonUtils.objectToJson(requestBody) : null);
    }

    public static JSONObject getRequest(String requestUrl, Map<String, String> requestHeader, Map<String, Object> requestBody) {
        return getJSONObjectByRequest(requestUrl, "GET", requestHeader, requestBody != null ? JsonUtils.objectToJson(requestBody) : null);
    }

    public static JSONObject postRequest(String requestUrl, Map<String, Object> requestBody) {
        Map<String, String> requestHeader = new HashMap<>(1);
        requestHeader.put("Content-Type", "application/json");
        return getJSONObjectByRequest(requestUrl, "POST", requestHeader, requestBody != null ? JsonUtils.objectToJson(requestBody) : null);
    }

    public static JSONObject getJSONObjectByRequest(String requestUrl, String requestMethod, Map<String, String> requestHeader, String requestBody) {
        try {
            // 请求服务
            String resStr = HttpRequestUtil.getDataByRequest(requestUrl, requestMethod, requestHeader, requestBody);
            // 返回结果转换格式
            return Optional.ofNullable(resStr).map(DataType::getDataByJSON).orElse(null);
        } catch (IOException ignored) {
        }
        return null;
    }

    /**
     * 查询HTTP请求连接
     *
     * @param requestUrl    请求路径
     * @param requestMethod 请求方式
     * @return 返回请求连接
     */
    private static HttpURLConnection getHttpConnection(String requestUrl, String requestMethod) {
        HttpURLConnection conn;
        try {
            URL uri = new URL(requestUrl);
            conn = (HttpURLConnection) uri.openConnection();
            // requestMethod: POST, PUT, DELETE, GET
            conn.setRequestMethod(requestMethod);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(120000); //60 secs
            conn.setReadTimeout(120000); //60 secs
            conn.setRequestProperty("Accept-Charset", "UTF-8");
            conn.setRequestProperty("contentType", "UTF-8");
        } catch (Exception ex) {
            throw new RuntimeException("connection failed.");
        }
        return conn;
    }
}
