package com.seer.teach.openapi.uitl;

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.time.Duration;
import java.util.Map;

/**
 * WebFlux 项目阻塞/非阻塞 HTTP 请求工具类
 * 支持 GET/POST 请求，可在阻塞线程池中执行阻塞调用，保证 Netty 线程不被阻塞
 */
@Component
public class HttpRequestUtils {

    private final RestTemplate restTemplate;

    public HttpRequestUtils() {
        this.restTemplate = new RestTemplate();
    }

    /**
     * 阻塞 GET 请求
     *
     * @param url 请求地址
     * @param headers 请求头，可为空
     * @return 响应结果字符串
     */
    public String get(String url, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            if (headers != null) {
                headers.forEach(httpHeaders::add);
            }
            HttpEntity<Void> entity = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
            return response.getBody();
        } catch (Exception e) {
            throw new RuntimeException("GET 请求失败: " + e.getMessage(), e);
        }
    }

    /**
     * 阻塞 POST 请求
     *
     * @param url 请求地址
     * @param body 请求体
     * @param headers 请求头，可为空
     * @return 响应结果字符串
     */
    public String post(String url, Object body, Map<String, String> headers) {
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            if (headers != null) {
                headers.forEach(httpHeaders::add);
            }
            HttpEntity<Object> entity = new HttpEntity<>(body, httpHeaders);
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
            return response.getBody();
        } catch (Exception e) {
            throw new RuntimeException("POST 请求失败: " + e.getMessage(), e);
        }
    }


    /**
     * 非阻塞 GET 请求
     *
     * @param url 请求地址
     * @param headers 请求头，可为空
     * @param timeout 超时时间
     * @return Mono 响应结果
     */
    public Mono<String> getAsync(String url, Map<String, String> headers, Duration timeout) {
        return Mono.fromCallable(() -> get(url, headers))
                .subscribeOn(Schedulers.boundedElastic())
                .timeout(timeout)
                .onErrorResume(e -> Mono.error(new RuntimeException("异步 GET 请求失败: " + e.getMessage(), e)));
    }

    /**
     * 非阻塞 POST 请求
     *
     * @param url 请求地址
     * @param body 请求体
     * @param headers 请求头，可为空
     * @param timeout 超时时间
     * @return Mono 响应结果
     */
    public Mono<String> postAsync(String url, Object body, Map<String, String> headers, Duration timeout) {
        return Mono.fromCallable(() -> post(url, body, headers))
                .subscribeOn(Schedulers.boundedElastic())
                .timeout(timeout)
                .onErrorResume(e -> Mono.error(new RuntimeException("异步 POST 请求失败: " + e.getMessage(), e)));
    }
}
