package com.ruoyi.lsfx.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.lsfx.exception.LsfxApiException;
import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.io.File;
import java.util.Map;

/**
 * HTTP请求工具类
 */
@Component
public class HttpUtil {

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

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private ObjectMapper objectMapper;

    public static org.springframework.core.io.Resource namedFileResource(File file, String filename) {
        return new NamedFileSystemResource(file, filename);
    }

    private static class NamedFileSystemResource extends FileSystemResource {
        private final String filename;

        NamedFileSystemResource(File file, String filename) {
            super(file);
            this.filename = StringUtils.hasText(filename) ? filename : file.getName();
        }

        @Override
        public String getFilename() {
            return filename;
        }
    }

    /**
     * 发送GET请求（带查询参数和请求头）
     * @param url 请求URL
     * @param params 查询参数
     * @param headers 请求头
     * @param responseType 响应类型
     * @return 响应对象
     */
    public <T> T get(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
        try {
            // 构建URL with查询参数
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
            if (params != null && !params.isEmpty()) {
                params.forEach((key, value) -> {
                    if (value != null) {
                        builder.queryParam(key, value);
                    }
                });
            }

            String fullUrl = builder.toUriString();
            log.debug("【HTTP GET】请求URL: {}", fullUrl);

            // 创建请求头
            HttpHeaders httpHeaders = new HttpHeaders();
            if (headers != null) {
                headers.forEach(httpHeaders::add);
            }

            // 构建请求实体
            HttpEntity<String> entity = new HttpEntity<>(httpHeaders);

            // 执行GET请求
            ResponseEntity<String> response = restTemplate.exchange(
                fullUrl,
                HttpMethod.GET,
                entity,
                String.class
            );

            log.debug("【HTTP GET】响应状态: {}", response.getStatusCode());
            log.debug("【HTTP GET】响应内容: {}", response.getBody());

            // 解析响应
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                return objectMapper.readValue(response.getBody(), responseType);
            } else {
                throw new LsfxApiException("GET请求失败: " + response.getStatusCode());
            }
        } catch (Exception e) {
            log.error("【HTTP GET】请求异常: url={}, error={}", url, e.getMessage(), e);
            throw new LsfxApiException("GET请求异常: " + e.getMessage(), e);
        }
    }

    /**
     * 发送GET请求（带请求头）
     * @param url 请求URL
     * @param headers 请求头
     * @param responseType 响应类型
     * @return 响应对象
     */
    public <T> T get(String url, Map<String, String> headers, Class<T> responseType) {
        try {
            HttpHeaders httpHeaders = createHeaders(headers);
            HttpEntity<Void> requestEntity = new HttpEntity<>(httpHeaders);

            ResponseEntity<T> response = restTemplate.exchange(
                url, HttpMethod.GET, requestEntity, responseType
            );

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new LsfxApiException("API调用失败，HTTP状态码: " + response.getStatusCode());
            }

            T body = response.getBody();
            if (body == null) {
                throw new LsfxApiException("API返回数据为空");
            }

            return body;
        } catch (RestClientException e) {
            throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 发送POST请求（JSON格式，带请求头）
     * @param url 请求URL
     * @param request 请求对象
     * @param headers 请求头
     * @param responseType 响应类型
     * @return 响应对象
     */
    public <T> T postJson(String url, Object request, Map<String, String> headers, Class<T> responseType) {
        try {
            HttpHeaders httpHeaders = createHeaders(headers);
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);

            HttpEntity<Object> requestEntity = new HttpEntity<>(request, httpHeaders);

            ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new LsfxApiException("API调用失败，HTTP状态码: " + response.getStatusCode());
            }

            T body = response.getBody();
            if (body == null) {
                throw new LsfxApiException("API返回数据为空");
            }

            return body;
        } catch (RestClientException e) {
            throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 发送POST请求（multipart/form-data格式，带请求头）
     * 用于提交表单数据（非文件上传场景）
     * @param url 请求URL
     * @param params 表单参数
     * @param headers 请求头
     * @param responseType 响应类型
     * @return 响应对象
     */
    public <T> T postFormData(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
        try {
            HttpHeaders httpHeaders = createHeaders(headers);
            httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

            MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
            if (params != null) {
                params.forEach(body::add);
            }

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, httpHeaders);

            ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new LsfxApiException("API调用失败，HTTP状态码: " + response.getStatusCode());
            }

            T responseBody = response.getBody();
            if (responseBody == null) {
                throw new LsfxApiException("API返回数据为空");
            }

            return responseBody;
        } catch (RestClientException e) {
            throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 发送POST请求（application/x-www-form-urlencoded格式，带请求头）
     * @param url 请求URL
     * @param params 表单参数
     * @param headers 请求头
     * @param responseType 响应类型
     * @return 响应对象
     */
    public <T> T postUrlEncodedForm(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
        try {
            HttpHeaders httpHeaders = createHeaders(headers);
            httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

            MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
            if (params != null) {
                params.forEach((key, value) -> {
                    if (value != null) {
                        body.add(key, value.toString());
                    }
                });
            }

            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, httpHeaders);

            ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new LsfxApiException("API调用失败，HTTP状态码: " + response.getStatusCode());
            }

            T responseBody = response.getBody();
            if (responseBody == null) {
                throw new LsfxApiException("API返回数据为空");
            }

            return responseBody;
        } catch (RestClientException e) {
            throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 发送POST请求（application/x-www-form-urlencoded格式）并返回原始JSON字符串
     * @param url 请求URL
     * @param params 表单参数
     * @param headers 请求头
     * @return 原始响应内容
     */
    public String postUrlEncodedFormForString(String url, Map<String, Object> params, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = createHeaders(headers);
            httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

            MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
            if (params != null) {
                params.forEach((key, value) -> {
                    if (value != null) {
                        body.add(key, value.toString());
                    }
                });
            }

            HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, httpHeaders);
            ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new LsfxApiException("API调用失败，HTTP状态码: " + response.getStatusCode());
            }

            String responseBody = response.getBody();
            if (responseBody == null) {
                throw new LsfxApiException("API返回数据为空");
            }

            return responseBody;
        } catch (RestClientException e) {
            throw new LsfxApiException("网络请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 上传文件（Multipart格式）
     * @param url 请求URL
     * @param params 参数（包含文件）
     * @param headers 请求头
     * @param responseType 响应类型
     * @return 响应对象
     */
    public <T> T uploadFile(String url, Map<String, Object> params, Map<String, String> headers, Class<T> responseType) {
        try {
            HttpHeaders httpHeaders = createHeaders(headers);
            httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

            MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
            if (params != null) {
                params.forEach((key, value) -> {
                    // 如果是File对象，包装为FileSystemResource
                    if (value instanceof File) {
                        File file = (File) value;
                        body.add(key, new FileSystemResource(file));
                    } else if (value instanceof org.springframework.core.io.Resource) {
                        body.add(key, value);
                    } else {
                        body.add(key, value);
                    }
                });
            }

            HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, httpHeaders);

            ResponseEntity<T> response = restTemplate.postForEntity(url, requestEntity, responseType);

            if (!response.getStatusCode().is2xxSuccessful()) {
                throw new LsfxApiException("文件上传失败，HTTP状态码: " + response.getStatusCode());
            }

            T responseBody = response.getBody();
            if (responseBody == null) {
                throw new LsfxApiException("文件上传返回数据为空");
            }

            return responseBody;
        } catch (RestClientException e) {
            throw new LsfxApiException("文件上传请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建请求头
     * @param headers 请求头Map
     * @return HttpHeaders对象
     */
    private HttpHeaders createHeaders(Map<String, String> headers) {
        HttpHeaders httpHeaders = new HttpHeaders();
        if (headers != null && !headers.isEmpty()) {
            headers.forEach(httpHeaders::set);
        }
        return httpHeaders;
    }
}
