package com.erp.ai.client;

import com.erp.ai.config.OpenClawProperties;
import com.erp.ai.exception.OpenClawException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestClientResponseException;

import java.util.List;
import java.util.Map;

/**
 * OpenClaw 외부 AI 엔진(port 18789) HTTP 클라이언트.
 * Spring RestClient(동기) 사용 — invyone 기존 RestTemplate 패턴과 일관성 유지.
 * enabled=false 이면 모든 메서드가 OpenClawException(503) 발생.
 */
@Slf4j
@Component
public class OpenClawClient {

    private final OpenClawProperties props;
    private final RestClient restClient;

    public OpenClawClient(OpenClawProperties props) {
        this.props = props;
        this.restClient = RestClient.builder()
                .baseUrl(props.getGatewayUrl())
                .defaultHeader("X-Pipeline-Source", "invyone")
                .build();
    }

    /**
     * OpenClaw 헬스 상태 확인.
     *
     * @return true = 정상, false = 응답 없음 또는 비정상
     */
    public boolean isHealthy() {
        if (!props.isEnabled()) {
            return false;
        }
        try {
            restClient.get()
                    .uri("/health")
                    .retrieve()
                    .toBodilessEntity();
            return true;
        } catch (Exception e) {
            log.warn("OpenClaw health check failed: {}", e.getMessage());
            return false;
        }
    }

    /**
     * OpenAI 호환 chat/completions 프록시.
     *
     * @param request OpenAI 형식 요청 맵 (model, messages, ...)
     * @return OpenAI 형식 응답 맵
     * @throws OpenClawException 비활성 또는 HTTP 오류 시
     */
    @SuppressWarnings("unchecked")
    public Map<String, Object> chatCompletion(Map<String, Object> request) {
        assertEnabled();
        try {
            return restClient.post()
                    .uri("/v1/chat/completions")
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(request)
                    .retrieve()
                    .body(Map.class);
        } catch (RestClientResponseException e) {
            log.error("OpenClaw chatCompletion HTTP error {}: {}", e.getStatusCode().value(), e.getMessage());
            throw new OpenClawException("OpenClaw 응답 오류: " + e.getMessage(), e.getStatusCode().value());
        } catch (ResourceAccessException e) {
            log.warn("OpenClaw chatCompletion connection failed: {}", e.getMessage());
            throw new OpenClawException("OpenClaw 연결 실패: " + e.getMessage(), e);
        }
    }

    /**
     * OpenClaw에서 사용 가능한 모델 목록 조회.
     *
     * @return 모델 ID 목록
     * @throws OpenClawException 비활성 또는 HTTP 오류 시
     */
    @SuppressWarnings("unchecked")
    public List<String> listModels() {
        assertEnabled();
        try {
            Map<String, Object> response = restClient.get()
                    .uri("/v1/models")
                    .retrieve()
                    .body(Map.class);
            if (response == null) {
                return List.of();
            }
            Object data = response.get("data");
            if (data instanceof List<?> list) {
                return list.stream()
                        .filter(item -> item instanceof Map)
                        .map(item -> (String) ((Map<?, ?>) item).get("id"))
                        .filter(id -> id != null)
                        .toList();
            }
            return List.of();
        } catch (RestClientResponseException e) {
            log.error("OpenClaw listModels HTTP error {}: {}", e.getStatusCode().value(), e.getMessage());
            throw new OpenClawException("OpenClaw 모델 목록 조회 오류: " + e.getMessage(), e.getStatusCode().value());
        } catch (ResourceAccessException e) {
            log.warn("OpenClaw listModels connection failed: {}", e.getMessage());
            throw new OpenClawException("OpenClaw 연결 실패: " + e.getMessage(), e);
        }
    }

    /**
     * OpenClaw auth profiles 동기화 (LLM API 키들).
     */
    public void syncAuthProfiles(Map<String, Object> body) {
        assertEnabled();
        try {
            restClient.post()
                    .uri("/v1/sync/auth-profiles")
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(body)
                    .retrieve()
                    .toBodilessEntity();
        } catch (RestClientResponseException e) {
            throw new OpenClawException("OpenClaw auth-profiles sync HTTP error: " + e.getMessage(), e.getStatusCode().value());
        } catch (ResourceAccessException e) {
            throw new OpenClawException("OpenClaw auth-profiles sync 연결 실패: " + e.getMessage(), e);
        }
    }

    /**
     * OpenClaw agents 동기화.
     */
    public void syncAgents(Map<String, Object> body) {
        assertEnabled();
        try {
            restClient.post()
                    .uri("/v1/sync/agents")
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(body)
                    .retrieve()
                    .toBodilessEntity();
        } catch (RestClientResponseException e) {
            throw new OpenClawException("OpenClaw agents sync HTTP error: " + e.getMessage(), e.getStatusCode().value());
        } catch (ResourceAccessException e) {
            throw new OpenClawException("OpenClaw agents sync 연결 실패: " + e.getMessage(), e);
        }
    }

    private void assertEnabled() {
        if (!props.isEnabled()) {
            throw new OpenClawException("OpenClaw 비활성 상태입니다. OPENCLAW_ENABLED=true 로 설정하세요.", 503);
        }
    }
}
