package com.emoon.tongue.service;

import cn.hutool.json.JSONUtil;
import com.emoon.common.core.domain.R;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.net.URI;
import java.net.http.HttpClient;
import java.time.Duration;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;

/**
 * 建档转发服务：把公网请求（method/query/header/body）原样转发到内网的指定接口，并将响应透传回去。
 *
 * 你后续给到“两个要转发的端口/url”后，只需要通过配置覆盖：
 * - create-record.target-base-url
 * - create-record.api1-path
 * - create-record.api2-path
 */
@Slf4j
@Service
public class CreateRecordService {

    /**
     * 内网目标服务根地址（不带结尾 /）
     *
     * 默认值会尝试复用 forward.target-base-url；若未配置则回退到 127.0.0.1，保证应用可启动。
     */
    @Value("${create-record.target-base-url:http://61.178.77.37:8100/service6}")
    private String targetBaseUrl;

    /**
     * 内网接口 path（以 / 开头），后续你给到真实接口后覆盖配置即可
     */
    @Value("${create-record.start-path:/start}")
    private String api1Path;

    @Value("${create-record.message-path:/message}")
    private String api2Path;

    @Value("${create-record.connect-timeout-ms:${forward.connect-timeout-ms:5000}}")
    private int connectTimeoutMs;

    @Value("${create-record.read-timeout-ms:${forward.read-timeout-ms:60000}}")
    private int readTimeoutMs;

    /**
     * 有些链路对 JDK HttpClient 报文更敏感；这里提供一次降级重试（与 ForwardService 逻辑一致）
     */
    private RestTemplate buildRestTemplate() {
        HttpClient client = HttpClient.newBuilder()
            .connectTimeout(Duration.ofMillis(connectTimeoutMs))
            .version(HttpClient.Version.HTTP_1_1)
            .build();
        JdkClientHttpRequestFactory rf = new JdkClientHttpRequestFactory(client);
        rf.setReadTimeout(Duration.ofMillis(readTimeoutMs));
        return new RestTemplate(rf);
    }

    private RestTemplate buildSimpleRestTemplate() {
        SimpleClientHttpRequestFactory rf = new SimpleClientHttpRequestFactory();
        rf.setConnectTimeout(connectTimeoutMs);
        rf.setReadTimeout(readTimeoutMs);
        return new RestTemplate(rf);
    }

    private String joinUrl(String base, String path) {
        String b = (base == null) ? "" : base.trim();
        String p = (path == null) ? "" : path.trim();
        if (b.endsWith("/")) b = b.substring(0, b.length() - 1);
        if (!p.startsWith("/")) p = "/" + p;
        return b + p;
    }

    private static final Set<String> HOP_BY_HOP_HEADERS = new HashSet<>(Arrays.asList(
        "connection",
        "keep-alive",
        "proxy-authenticate",
        "proxy-authorization",
        "te",
        "trailer",
        "transfer-encoding",
        "upgrade",
        "content-length",
        "host"
    ));

    private ResponseEntity<String> passthroughResponse(ResponseEntity<String> upstream) {
        if (upstream == null) {
            return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
                .contentType(MediaType.APPLICATION_JSON)
                .body(JSONUtil.toJsonStr(R.fail("转发失败：上游无响应")));
        }
        HttpHeaders out = new HttpHeaders();
        // 尽量透传上游响应头（过滤 hop-by-hop）
        for (var e : upstream.getHeaders().entrySet()) {
            String name = e.getKey();
            if (!StringUtils.hasText(name)) continue;
            if (HOP_BY_HOP_HEADERS.contains(name.toLowerCase(Locale.ROOT))) continue;
            for (String v : e.getValue()) {
                out.add(name, v);
            }
        }
        return new ResponseEntity<>(upstream.getBody(), out, upstream.getStatusCode());
    }

    public ResponseEntity<String> forwardStart(HttpServletRequest request, byte[] body) {
        return forward(request, body, api1Path);
    }

    public ResponseEntity<String> forwardMessage(HttpServletRequest request, byte[] body) {
        return forward(request, body, api2Path);
    }

    private ResponseEntity<String> forward(HttpServletRequest request, byte[] body, String upstreamPath) {
        String baseUrl = targetBaseUrl;
        String url = joinUrl(baseUrl, upstreamPath);
        String qs = request != null ? request.getQueryString() : null;
        if (StringUtils.hasText(qs)) {
            url = url + (url.contains("?") ? "&" : "?") + qs;
        }

        try {
            HttpMethod method = HttpMethod.POST;
            if (request != null && StringUtils.hasText(request.getMethod())) {
                try {
                    method = HttpMethod.valueOf(request.getMethod().trim().toUpperCase(Locale.ROOT));
                } catch (IllegalArgumentException ignore) {
                    // 兼容：未知 method 直接回退到 POST（本转发仅用于已知的 POST JSON 接口）
                    method = HttpMethod.POST;
                }
            }

            HttpHeaders headers = new HttpHeaders();
            if (request != null) {
                Enumeration<String> names = request.getHeaderNames();
                while (names != null && names.hasMoreElements()) {
                    String name = names.nextElement();
                    if (!StringUtils.hasText(name)) continue;
                    // Host/Content-Length 由底层客户端计算更安全
                    if (HttpHeaders.HOST.equalsIgnoreCase(name) || HttpHeaders.CONTENT_LENGTH.equalsIgnoreCase(name)) {
                        continue;
                    }
                    Enumeration<String> values = request.getHeaders(name);
                    while (values != null && values.hasMoreElements()) {
                        headers.add(name, values.nextElement());
                    }
                }
            }

            HttpEntity<byte[]> entity = new HttpEntity<>(body == null ? new byte[0] : body, headers);

            ResponseEntity<String> resp;
            try {
                resp = buildRestTemplate().exchange(URI.create(url), method, entity, String.class);
            } catch (ResourceAccessException e) {
                log.warn("建档转发 JDK HttpClient 失败，尝试降级为 HttpURLConnection 重试，url={}, reason={}", url, e.getMessage());
                resp = buildSimpleRestTemplate().exchange(URI.create(url), method, entity, String.class);
            }
            return passthroughResponse(resp);
        } catch (Exception e) {
            log.error("建档转发失败，url={}", url, e);
            return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
                .contentType(MediaType.APPLICATION_JSON)
                .body(JSONUtil.toJsonStr(R.fail("转发失败：" + e.getMessage())));
        }
    }
}
