package com.kingdee.eas.custom.integration.weaver.util;

import com.kingdee.eas.custom.integration.base.config.AppConfig;
import com.kingdee.eas.custom.integration.base.exception.ErrorCode;
import com.kingdee.eas.custom.integration.weaver.config.WeaverConfig;
import com.kingdee.eas.custom.integration.weaver.exception.WeaverErrorCodes;
import com.kingdee.eas.custom.integration.weaver.exception.WeaverIntegrationException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * 泛微 E10 OAuth2 HTTP 工具。
 */
public final class WeaverApiUtils {

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

    private static final String[] USER_ID_KEYS = {
            "id", "workcode", "jobNum", "job_number", "account", "username", "loginId"
    };

    private WeaverApiUtils() {
    }

    @SuppressWarnings("unchecked")
    public static String exchangeAccessToken(RestTemplate restTemplate,
                                             WeaverConfig weaverConfig,
                                             AppConfig appConfig,
                                             String code) {
        String url = UriComponentsBuilder.fromHttpUrl(weaverConfig.getAccessTokenUrl())
                .queryParam("grant_type", "authorization_code")
                .queryParam("client_id", appConfig.getAppId())
                .queryParam("client_secret", appConfig.getAppSecret())
                .queryParam("code", code)
                .queryParam("redirect_uri", appConfig.getCallbackUrl())
                .build()
                .toUriString();

        log.info("开始换取 access_token, client_id={}", appConfig.getAppId());
        ResponseEntity<Map> response = restTemplate.postForEntity(
                url, new HttpEntity<>(buildJsonHeaders()), Map.class);
        Map<String, Object> body = response.getBody();
        assertSuccess(body, WeaverErrorCodes.TOKEN_FAILED, "换取 access_token");

        String accessToken = extractString(body, "access_token");
        if (StringUtils.isBlank(accessToken) && body.get("data") instanceof Map) {
            accessToken = extractString((Map<String, Object>) body.get("data"), "access_token");
        }
        if (StringUtils.isBlank(accessToken)) {
            throw new WeaverIntegrationException(WeaverErrorCodes.TOKEN_FAILED, "access_token 为空");
        }
        return accessToken;
    }

    @SuppressWarnings("unchecked")
    public static String fetchProfileId(RestTemplate restTemplate,
                                        WeaverConfig weaverConfig,
                                        String accessToken) {
        String url = UriComponentsBuilder.fromHttpUrl(weaverConfig.getProfileUrl())
                .queryParam("access_token", accessToken)
                .build()
                .toUriString();

        log.info("开始获取用户信息");
        ResponseEntity<Map> response = restTemplate.postForEntity(
                url, new HttpEntity<>(buildJsonHeaders()), Map.class);
        Map<String, Object> body = response.getBody();
        assertSuccess(body, WeaverErrorCodes.PROFILE_FAILED, "获取用户信息");

        String userId = extractUserId(body);
        if (StringUtils.isBlank(userId) && body.get("data") instanceof Map) {
            userId = extractUserId((Map<String, Object>) body.get("data"));
        }
        if (StringUtils.isBlank(userId)) {
            throw new WeaverIntegrationException(WeaverErrorCodes.USER_ID_EMPTY);
        }
        log.info("获取用户信息成功: {}", userId);
        return userId;
    }

    public static String buildLogoutUrl(WeaverConfig weaverConfig, String serviceUrl) {
        if (weaverConfig == null || !weaverConfig.isConfigured()) {
            throw new WeaverIntegrationException(WeaverErrorCodes.CONFIG_MISSING);
        }
        // service 交由 UriComponentsBuilder 编码，勿先 URLEncoder 再 build(true)
        return UriComponentsBuilder.fromHttpUrl(weaverConfig.getLogoutUrl())
                .queryParam("service", serviceUrl)
                .encode(StandardCharsets.UTF_8)
                .build()
                .toUriString();
    }

    private static HttpHeaders buildJsonHeaders() {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return headers;
    }

    @SuppressWarnings("unchecked")
    private static String extractUserId(Map<String, Object> body) {
        if (body == null) {
            return null;
        }
        for (String key : USER_ID_KEYS) {
            String value = extractString(body, key);
            if (StringUtils.isNotBlank(value)) {
                return value;
            }
        }
        Object attributes = body.get("attributes");
        if (attributes instanceof Map) {
            Map<String, Object> attrMap = (Map<String, Object>) attributes;
            for (String key : USER_ID_KEYS) {
                String value = extractString(attrMap, key);
                if (StringUtils.isNotBlank(value)) {
                    return value;
                }
            }
        }
        return null;
    }

    private static String extractString(Map<String, Object> map, String key) {
        if (map == null || key == null) {
            return null;
        }
        Object value = map.get(key);
        return value == null ? null : value.toString().trim();
    }

    private static void assertSuccess(Map<String, Object> body, ErrorCode errorCode, String action) {
        if (body == null) {
            throw new WeaverIntegrationException(errorCode, action + "响应体为空");
        }
        Object code = body.get("code");
        if (code != null && !"0".equals(String.valueOf(code))) {
            Object msg = body.get("msg");
            throw new WeaverIntegrationException(errorCode,
                    action + "失败:" + (msg != null ? msg : body));
        }
        Object status = body.get("status");
        if (status != null && !"200".equals(String.valueOf(status))) {
            Object msg = body.get("msg");
            throw new WeaverIntegrationException(errorCode,
                    action + "失败:" + (msg != null ? msg : body));
        }
    }
}
