package org.dromara.system.config;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.service.ISysConfigService;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Slf4j
@Component
public class OneHttpConfig {

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private ISysConfigService sysConfigService;

    // 全局后台管理员TOKEN配置key
    private static final String KEY_ADMIN_TOKEN = "ai.oneapi.adminToken";

    // 缓存请求头
    private HttpHeaders adminHeaders;

    /** 获取配置值 */
    public String getConfig(String key) {
        return sysConfigService.getConfigByKey(key);
    }

    /**
     * 构建请求头
     * 优先级：当前登录用户token > 全局后台管理员token
     */
    public synchronized HttpHeaders getAdminHeader() {
        // 每次都重新判断，不要全局缓存死Token，切换租户/登录用户自动刷新
        return buildDynamicHeader();
    }

    /** 动态构建请求头：优先用户自身Token */
    private HttpHeaders buildDynamicHeader() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 1. 优先获取当前登录用户自己的 oneapi token
        String userOneApiToken = LoginHelper.getLoginUser().getTenantKey();
        if (!LoginHelper.getLoginUser().getAdmin()) {
            headers.set("Authorization", "Bearer " + userOneApiToken);
            return headers;
        }else {
            // 2. 用户没有配置，降级使用全局管理员Token
            String globalAdminToken = getConfig(KEY_ADMIN_TOKEN);
            if (!StringUtils.hasText(globalAdminToken)) {
                throw new RuntimeException("未配置全局OneAPI管理员令牌，且当前用户未配置个人令牌");
            }
            headers.set("Authorization", "Bearer " + globalAdminToken);
            return headers;
        }
    }

    /** 获取接口基础地址 */
    private String getBaseUrl() {
        String base = getConfig("ai.oneapi.baseUrl");
        if (!StringUtils.hasText(base)) {
            throw new RuntimeException("请先配置系统参数【ai.oneapi.baseUrl】");
        }
        return base.endsWith("/") ? base : base + "/";
    }

    /** 原样拼接URL 不做任何编码，和curl直接传中文完全一致 */
    public String buildUrl(String path, Map<String, String> queryParams) {
        String baseUrl = getBaseUrl();
        String apiPath = path.startsWith("/") ? path.substring(1) : path;
        StringBuilder url = new StringBuilder(baseUrl + apiPath);
        if (!CollectionUtils.isEmpty(queryParams)) {
            url.append("?");
            int idx = 0;
            for (Map.Entry<String, String> entry : queryParams.entrySet()) {
                if (idx > 0) {
                    url.append("&");
                }
                url.append(entry.getKey()).append("=").append(entry.getValue());
                idx++;
            }
        }
        return url.toString();
    }

    /** 获取超时时间 */
    public int getTimeoutMs() {
        String val = getConfig("ai.oneapi.timeout");
        try {
            return StringUtils.hasText(val) ? Integer.parseInt(val) : 10000;
        } catch (NumberFormatException e) {
            log.warn("ai.oneapi.timeout 配置错误，使用默认10000ms");
            return 10000;
        }
    }

    // ===================== 请求方法 =====================

    public <T> T get(String path, Map<String, String> queryParams, ParameterizedTypeReference<T> typeRef) {
        String url = buildUrl(path, queryParams);
        HttpEntity<Void> entity = new HttpEntity<>(getAdminHeader());
        try {
            ResponseEntity<T> resp = restTemplate.exchange(url, HttpMethod.GET, entity, typeRef);
            return resp.getBody();
        } catch (HttpStatusCodeException e) {
            log.error("OneAPI-GET 请求异常 url:{}, code:{}, res:{}", url, e.getRawStatusCode(), e.getResponseBodyAsString());
            throw new RuntimeException("远程接口调用失败：" + e.getRawStatusCode());
        }
    }

    public <T> T get(String path, ParameterizedTypeReference<T> typeRef) {
        return get(path, null, typeRef);
    }

    public <T> T post(String path, Object body, ParameterizedTypeReference<T> typeRef) {
        String url = buildUrl(path, null);
        HttpEntity<Object> entity = new HttpEntity<>(body, getAdminHeader());
        try {
            ResponseEntity<T> resp = restTemplate.exchange(url, HttpMethod.POST, entity, typeRef);
            return resp.getBody();
        } catch (HttpStatusCodeException e) {
            log.error("OneAPI-POST 请求异常 url:{}, code:{}, res:{}", url, e.getRawStatusCode(), e.getResponseBodyAsString());
            throw new RuntimeException("远程接口调用失败：" + e.getRawStatusCode());
        }
    }

    public <T> T put(String path, Object body, ParameterizedTypeReference<T> typeRef) {
        String url = buildUrl(path, null);
        HttpEntity<Object> entity = new HttpEntity<>(body, getAdminHeader());
        try {
            ResponseEntity<T> resp = restTemplate.exchange(url, HttpMethod.PUT, entity, typeRef);
            return resp.getBody();
        } catch (HttpStatusCodeException e) {
            log.error("OneAPI-PUT 请求异常 url:{}, code:{}, res:{}", url, e.getRawStatusCode(), e.getResponseBodyAsString());
            throw new RuntimeException("远程接口调用失败：" + e.getRawStatusCode());
        }
    }

    public <T> T delete(String path, ParameterizedTypeReference<T> typeRef) {
        String url = buildUrl(path, null);
        HttpEntity<Void> entity = new HttpEntity<>(getAdminHeader());
        try {
            ResponseEntity<T> resp = restTemplate.exchange(url, HttpMethod.DELETE, entity, typeRef);
            return resp.getBody();
        } catch (HttpStatusCodeException e) {
            log.error("OneAPI-DELETE 请求异常 url:{}, code:{}, res:{}", url, e.getRawStatusCode(), e.getResponseBodyAsString());
            throw new RuntimeException("远程接口调用失败：" + e.getRawStatusCode());
        }
    }

}
