package com.fs.wxwork.utils;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.fs.common.exception.base.BaseException;
import com.fs.ipad.enums.ErrCodeEnum;
import com.fs.wxwork.dto.WxWorkResponseCodeDTO;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * HTTP请求工具类（基于Hutool封装）
 * 增强功能：请求参数、Header和响应日志记录
 */
@Slf4j
public class WxWorkHttpUtilNew {
    private static final Logger logger = LoggerFactory.getLogger(WxWorkHttpUtilNew.class);

    /**
     * 发送GET请求
     * @param url 请求URL
     * @return 响应字符串
     */
    public static String get(String url) {
        return get(url, null, null);
    }

    /**
     * 发送带参数的GET请求
     * @param url 请求URL
     * @param params 请求参数
     * @return 响应字符串
     */
    public static String get(String url, Map<String, Object> params) {
        return get(url, params, null);
    }

    /**
     * 发送带参数和Header的GET请求
     * @param url 请求URL
     * @param params 请求参数
     * @param headers 请求头
     * @return 响应字符串
     */
    public static String get(String url, Map<String, Object> params, Map<String, String> headers) {
        // 记录请求信息
        logRequest("GET", url, params, null, headers);

        // 构建请求
        HttpRequest request = HttpRequest.get(url);

        // 添加参数
        if (MapUtil.isNotEmpty(params)) {
            request.form(params);
        }

        // 添加请求头
        if (MapUtil.isNotEmpty(headers)) {
            request.addHeaders(headers);
        }

        // 执行请求并获取响应
        HttpResponse response = request.execute();
        String responseBody = response.body();

        // 记录响应信息
        logResponse(response, responseBody);

        return responseBody;
    }
    /**
     * 发送POST请求（JSON格式）
     *
     * @param url      请求URL
     * @param jsonBody JSON请求体
     * @param serverId
     * @return 响应字符串
     */
    public static <T> T postWithType(String url, Object jsonBody, TypeReference<T> type, Long serverId) {
        String json = JSON.toJSONString(jsonBody);
        String post = post(url, json, null, serverId);
        WxWorkResponseCodeDTO respone = JSON.parseObject(post, WxWorkResponseCodeDTO.class);
        if(respone.getErrcode() != 0){
            log.error("请求服务器地址：{}，请求参数：{}，返回数据：{}，请求时间：{}", url, json, JSON.toJSONString(respone), LocalDateTime.now());
            String errMsg = ErrCodeEnum.getErrMsg(respone.getErrcode());
            if("未知的服务端错误".equals(errMsg)){
                errMsg = respone.getErrmsg();
            }
            throw new BaseException(errMsg);
        }
        return JSON.parseObject(post, type);
    }
    /**
     * 发送带Header的POST请求（JSON格式）
     * @param url 请求URL
     * @param jsonBody JSON请求体
     * @param headers 请求头
     * @return 响应字符串
     */
    public static String post(String url, String jsonBody, Map<String, String> headers, Long serviceId) {
        // 记录请求信息
        logRequest("POST", url, null, jsonBody, headers);

        // 构建请求
        HttpRequest request = HttpRequest.post(url)
                .body(jsonBody);

        // 添加请求头
        if (MapUtil.isNotEmpty(headers)) {
            request.addHeaders(headers);
        }

        // 执行请求并获取响应
        HttpResponse response;
        try {
            response = request.execute();
        }catch (IORuntimeException e){
            return "{\"data\":null,\"errcode\":400,\"errmsg\":\"连接超时，服务器宕机 - serviceId: " + serviceId +"\"}";
        }
        String responseBody = response.body();

        // 记录响应信息
        logResponse(response, responseBody);

        return responseBody;
    }

    /**
     * 发送表单POST请求
     * @param url 请求URL
     * @param formParams 表单参数
     * @return 响应字符串
     */
    public static String postForm(String url, Map<String, Object> formParams) {
        return postForm(url, formParams, null);
    }

    /**
     * 发送带Header的表单POST请求
     * @param url 请求URL
     * @param formParams 表单参数
     * @param headers 请求头
     * @return 响应字符串
     */
    public static String postForm(String url, Map<String, Object> formParams, Map<String, String> headers) {
        // 记录请求信息
        logRequest("POST", url, formParams, null, headers);

        // 构建请求
        HttpRequest request = HttpRequest.post(url);

        // 添加表单参数
        if (MapUtil.isNotEmpty(formParams)) {
            request.form(formParams);
        }

        // 添加请求头
        if (MapUtil.isNotEmpty(headers)) {
            request.addHeaders(headers);
        }

        // 执行请求并获取响应
        HttpResponse response = request.execute();
        String responseBody = response.body();

        // 记录响应信息
        logResponse(response, responseBody);

        return responseBody;
    }

    /**
     * 发送PUT请求（JSON格式）
     * @param url 请求URL
     * @param jsonBody JSON请求体
     * @return 响应字符串
     */
    public static String put(String url, String jsonBody) {
        return put(url, jsonBody, null);
    }

    /**
     * 发送带Header的PUT请求（JSON格式）
     * @param url 请求URL
     * @param jsonBody JSON请求体
     * @param headers 请求头
     * @return 响应字符串
     */
    public static String put(String url, String jsonBody, Map<String, String> headers) {
        // 记录请求信息
        logRequest("PUT", url, null, jsonBody, headers);

        // 构建请求
        HttpRequest request = HttpRequest.put(url)
                .body(jsonBody);

        // 添加请求头
        if (MapUtil.isNotEmpty(headers)) {
            request.addHeaders(headers);
        }

        // 执行请求并获取响应
        HttpResponse response = request.execute();
        String responseBody = response.body();

        // 记录响应信息
        logResponse(response, responseBody);

        return responseBody;
    }

    /**
     * 发送DELETE请求
     * @param url 请求URL
     * @return 响应字符串
     */
    public static String delete(String url) {
        return delete(url, null);
    }

    /**
     * 发送带Header的DELETE请求
     * @param url 请求URL
     * @param headers 请求头
     * @return 响应字符串
     */
    public static String delete(String url, Map<String, String> headers) {
        // 记录请求信息
        logRequest("DELETE", url, null, null, headers);

        // 构建请求
        HttpRequest request = HttpRequest.delete(url);

        // 添加请求头
        if (MapUtil.isNotEmpty(headers)) {
            request.addHeaders(headers);
        }

        // 执行请求并获取响应
        HttpResponse response = request.execute();
        String responseBody = response.body();

        // 记录响应信息
        logResponse(response, responseBody);

        return responseBody;
    }

    /**
     * 记录请求信息
     * @param method 请求方法
     * @param url 请求URL
     * @param params 请求参数
     * @param body 请求体
     * @param headers 请求头
     */
    private static void logRequest(String method, String url, Map<String, Object> params, String body, Map<String, String> headers) {
        logger.debug("发送请求: {} {}", method, url);

        if (MapUtil.isNotEmpty(params)) {
            logger.debug("请求参数: {}", JSONUtil.toJsonStr(params));
        }

        if (body != null && !body.isEmpty()) {
            // 如果是较长的JSON，可能需要截断
            String logBody = body.length() > 1000 ? body.substring(0, 1000) + "... (截断)" : body;
            logger.debug("请求体: {}", logBody);
        }

        if (MapUtil.isNotEmpty(headers)) {
            logger.debug("请求头: {}", JSONUtil.toJsonStr(headers));
        }
    }

    /**
     * 记录响应信息
     * @param response 响应对象
     * @param responseBody 响应体
     */
    private static void logResponse(HttpResponse response, String responseBody) {
        logger.debug("响应状态码: {}", response.getStatus());

        // 记录响应头
        Map<String, List<String>> headers = response.headers();
        if (MapUtil.isNotEmpty(headers)) {
            logger.debug("响应头: {}", JSONUtil.toJsonStr(headers));
        }

        // 记录响应体，但限制大小以防止日志过大
        if (responseBody != null && !responseBody.isEmpty()) {
            String logBody = responseBody.length() > 1000 ?
                    responseBody.substring(0, 1000) + "... (截断)" : responseBody;
            logger.debug("响应体: {}", logBody);
        }
    }
}
