package com.zioinfo.signage.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;

/**
 * Ollama 온프레미스 AI 클라이언트.
 * 보안 불변 규칙: 외부 AI API 절대 금지 — Ollama localhost:11434만 허용.
 * 연결 실패 시 폴백 응답 반환(예외 미전파).
 */
@Slf4j
@Component
public class OllamaClient {

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

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

    private final HttpClient http = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(5))
        .build();
    private final ObjectMapper mapper = new ObjectMapper();

    public String chat(String prompt) {
        return chat(prompt, "ESN AI 이상 분석 전문가 역할입니다.");
    }

    public String chat(String prompt, String systemPrompt) {
        try {
            var body = Map.of(
                "model", model,
                "messages", new Object[]{
                    Map.of("role", "system", "content", systemPrompt),
                    Map.of("role", "user",   "content", prompt)
                },
                "stream", false
            );
            String json = mapper.writeValueAsString(body);
            HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create(baseUrl + "/api/chat"))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .timeout(Duration.ofSeconds(120))
                .build();
            HttpResponse<String> resp = http.send(req, HttpResponse.BodyHandlers.ofString());
            if (resp.statusCode() == 200) {
                var res = mapper.readTree(resp.body());
                return res.path("message").path("content").asText("분석 결과를 생성했습니다.");
            }
            return fallback(prompt);
        } catch (Exception e) {
            log.warn("Ollama 연결 실패 — 폴백 응답 반환: {}", e.getMessage());
            return fallback(prompt);
        }
    }

    /**
     * 평문 텍스트 생성(모델 지정). AiTextRouter/AiConfigService 연결 테스트 진입점.
     *
     * <p>{@link #chat(String, String)} 과 달리 <b>실패 시 규칙기반 폴백 문자열을 만들지 않고 {@code null}</b>
     * 을 반환한다(라우터가 degraded 로 감지해 다음 단계 폴백을 수행하게 하기 위함).
     *
     * @param prompt        사용자 프롬프트(시스템 지시 포함 가능)
     * @param modelOverride 사용할 Ollama 모델(null/blank 이면 서버 기본 {@code guardia.ollama-text-model})
     * @return 생성 텍스트(성공) 또는 {@code null}(비200/타임아웃/예외/빈응답)
     */
    public String generateText(String prompt, String modelOverride) {
        if (prompt == null || prompt.isBlank()) {
            return null;
        }
        String useModel = (modelOverride == null || modelOverride.isBlank()) ? model : modelOverride;
        try {
            var body = Map.of(
                "model", useModel,
                "messages", new Object[]{ Map.of("role", "user", "content", prompt) },
                "stream", false
            );
            String json = mapper.writeValueAsString(body);
            HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create(baseUrl + "/api/chat"))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(json))
                .timeout(Duration.ofSeconds(120))
                .build();
            HttpResponse<String> resp = http.send(req, HttpResponse.BodyHandlers.ofString());
            if (resp.statusCode() == 200) {
                var res = mapper.readTree(resp.body());
                String text = res.path("message").path("content").asText("");
                return (text == null || text.isBlank()) ? null : text.trim();
            }
            log.warn("Ollama generateText status {} — null 반환(라우터 폴백)", resp.statusCode());
            return null;
        } catch (Exception e) {
            log.warn("Ollama generateText 실패 — null 반환(라우터 폴백): {}", e.getClass().getSimpleName());
            return null;
        }
    }

    private String fallback(String prompt) {
        if (prompt.toLowerCase().contains("alarm") || prompt.contains("알람")) {
            return "알람 분석: 장치 연결 상태를 확인하고 네트워크 환경을 점검하세요. 지속 발생 시 현장 엔지니어 파견이 필요합니다.";
        }
        if (prompt.toLowerCase().contains("pos") || prompt.contains("가격")) {
            return "POS 데이터 분류: 정상 가격 변환 데이터입니다. 이상 감지된 항목은 수동 검토가 필요합니다.";
        }
        return "AI 분석 결과: 현재 시스템 상태를 검토하고 운영 매뉴얼을 참조하세요.";
    }
}
