package com.zioinfo.hrm.common.ai;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;

import java.time.Duration;
import java.util.Map;

/**
 * 온프레미스 Ollama 평문 텍스트 생성 클라이언트. [GUARDiA-HRM]
 *
 * <p>기존 {@code AiService} 의 Ollama 호출 로직을 라우터/설정 테스트와 공용으로 쓰기 위해 분리한 얇은
 * 컴포넌트. {@code /api/generate}(stream=false) 로 호출하고 응답의 {@code response} 문자열만 반환한다.
 * 실패(미가용/타임아웃/예외) 시 {@code null} 을 반환한다(예외 미전파 → 호출자 폴백).
 *
 * <p><b>보안 불변</b>: base-url 은 온프레미스 Ollama(localhost:11434) 전용 — 외부 AI API 금지.
 * 콜드로드(소형/중형 모델) 대비 타임아웃 120s.
 */
@Slf4j
@Component
public class OllamaTextClient {

    @Value("${guardia.ollama-url:http://localhost:11434}")
    private String ollamaUrl;

    @Value("${guardia.ollama-text-model:llama3}")
    private String defaultModel;

    private static final int TIMEOUT_SEC = 120;

    private WebClient client() {
        return WebClient.builder().baseUrl(ollamaUrl)
                .codecs(c -> c.defaultCodecs().maxInMemorySize(4 * 1024 * 1024))
                .build();
    }

    /**
     * 평문 텍스트 생성. 실패 시 {@code null}(예외 미전파).
     *
     * @param prompt 프롬프트
     * @param model  모델 태그(null/blank 이면 서버 기본 모델)
     * @return 생성 텍스트 또는 null
     */
    @SuppressWarnings("unchecked")
    public String generate(String prompt, String model) {
        if (prompt == null || prompt.isBlank()) {
            return null;
        }
        String useModel = (model == null || model.isBlank()) ? defaultModel : model.trim();
        try {
            Map<String, Object> body = Map.of("model", useModel, "prompt", prompt, "stream", false);
            Map<String, Object> resp = client().post().uri("/api/generate")
                    .bodyValue(body)
                    .retrieve()
                    .bodyToMono(Map.class)
                    .timeout(Duration.ofSeconds(TIMEOUT_SEC))
                    .block();
            if (resp == null) {
                return null;
            }
            Object r = resp.get("response");
            String out = r == null ? null : r.toString();
            return (out == null || out.isBlank()) ? null : out;
        } catch (Exception e) {
            log.warn("Ollama generate 실패(폴백): {}", e.getClass().getSimpleName());
            return null;
        }
    }
}
