package com.jeesharp.business.modules.setting.application.support;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 在当前管理端请求上下文中，以相同登录态 POST 调用注册表配置的管理端列表接口。
 *
 * @author jeesharp
 * @since 2026-07-03
 */
@Slf4j
@Component
public class AdminInProcessListClient {

    @Value("${jeesharp.web.adminPath:/admin}")
    private String adminPath;

    /**
     * @param adminListUrl 注册表 {@code admin_list_url}，如 {@code /manager/business/mall/spu/v1/list}
     * @param jsonBody     POST JSON 请求体
     * @return 响应正文；无请求上下文或调用失败时返回 {@code null}
     */
    public String postAdminList(String adminListUrl, String jsonBody) {
        if (StrUtil.isBlank(adminListUrl)) {
            return null;
        }
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attrs == null) {
            log.debug("AdminInProcessListClient: no servlet request context, skip {}", adminListUrl);
            return null;
        }
        HttpServletRequest request = attrs.getRequest();
        String path = normalizeAdminListPath(adminListUrl.trim());
        String url = buildLocalUrl(request, path);
        return executePost(request, url, jsonBody);
    }

    /**
     * 由注册表列表 URL 推导详情 URL（{@code /list} → {@code /info?id=}），GET 拉取单条。
     */
    public String getAdminInfo(String adminListUrl, String id) {
        if (StrUtil.isBlank(adminListUrl) || StrUtil.isBlank(id)) {
            return null;
        }
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attrs == null) {
            log.debug("AdminInProcessListClient: no servlet request context, skip info {}", adminListUrl);
            return null;
        }
        HttpServletRequest request = attrs.getRequest();
        String infoPath = deriveInfoPath(adminListUrl.trim(), id.trim());
        String path = normalizeAdminListPath(infoPath);
        String url = buildLocalUrl(request, path);
        return executeGet(request, url);
    }

    private String executePost(HttpServletRequest request, String url, String jsonBody) {
        try {
            HttpRequest httpRequest = HttpRequest.post(url)
                    .timeout(15_000)
                    .header(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8")
                    .body(jsonBody);
            applyAuthorization(request, httpRequest);
            HttpResponse response = httpRequest.execute();
            if (!response.isOk()) {
                log.warn("AdminInProcessListClient: HTTP {} for {}", response.getStatus(), url);
                return null;
            }
            return response.body();
        } catch (Exception ex) {
            log.warn("AdminInProcessListClient: failed {} - {}", url, ex.getMessage());
            return null;
        }
    }

    private String executeGet(HttpServletRequest request, String url) {
        try {
            HttpRequest httpRequest = HttpRequest.get(url).timeout(15_000);
            applyAuthorization(request, httpRequest);
            HttpResponse response = httpRequest.execute();
            if (!response.isOk()) {
                log.warn("AdminInProcessListClient: HTTP {} for {}", response.getStatus(), url);
                return null;
            }
            return response.body();
        } catch (Exception ex) {
            log.warn("AdminInProcessListClient: failed {} - {}", url, ex.getMessage());
            return null;
        }
    }

    private static void applyAuthorization(HttpServletRequest request, HttpRequest httpRequest) {
        String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StrUtil.isNotBlank(authorization)) {
            httpRequest.header(HttpHeaders.AUTHORIZATION, authorization);
        }
    }

    private static String deriveInfoPath(String adminListUrl, String id) {
        String path = adminListUrl.startsWith("/") ? adminListUrl : "/" + adminListUrl;
        if (path.endsWith("/list")) {
            path = path.substring(0, path.length() - "/list".length()) + "/info";
        } else if (!path.contains("/info")) {
            path = path + "/info";
        }
        return path + "?id=" + id;
    }

    private String normalizeAdminListPath(String adminListUrl) {
        String path = adminListUrl.startsWith("/") ? adminListUrl : "/" + adminListUrl;
        if (!path.startsWith(adminPath)) {
            path = adminPath + path;
        }
        return path;
    }

    private static String buildLocalUrl(HttpServletRequest request, String path) {
        String contextPath = StrUtil.nullToEmpty(request.getContextPath());
        return request.getScheme()
                + "://"
                + request.getLocalAddr()
                + ":"
                + request.getLocalPort()
                + contextPath
                + path;
    }
}
