package com.zioinfo.esn.controller;

import com.zioinfo.esn.ai.service.AiTextRouter;
import com.zioinfo.esn.common.ApiResponse;
import com.zioinfo.esn.common.ai.TextAiClient.GenResult;
import com.zioinfo.esn.config.OllamaClient;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.Map;

/**
 * ESN 텍스트 AI(알람 원인분석·POS 자동분류·운영 채팅) 진입점.
 *
 * <p><b>provider 라우팅</b>: {@link AiTextRouter} 를 경유해 Claude(외부, 키 설정 시)↔Ollama(온프레미스,
 * qwen3/deepseek/glm/기존소형)를 런타임 선택한다. 라우터가 degraded 를 반환하면(키 미설정·전 provider 실패)
 * 기존 {@link OllamaClient#chat} 규칙기반 폴백으로 최종 방어 — 응답은 항상 비어있지 않다(무회귀).
 *
 * <p>보안 불변: 외부 AI 는 Claude(소유자 승인 예외) 단일 경로. 그 외 외부 호출 금지. 키/스택 미노출.
 */
@RestController
@RequestMapping("/api/ai")
@RequiredArgsConstructor
public class AiController {

    private final AiTextRouter aiRouter;
    private final OllamaClient ollama;

    /**
     * 알람 AI 이상 분석 — provider 라우팅(Claude↔Ollama), 실패 시 규칙기반 폴백.
     */
    @PostMapping("/analyze-alarm")
    public ApiResponse<Map<String, String>> analyzeAlarm(@RequestBody Map<String, Object> body) {
        String alarmType = (String) body.getOrDefault("alarmType", "UNKNOWN");
        String message   = (String) body.getOrDefault("message", "");
        String severity  = (String) body.getOrDefault("severity", "LOW");

        String system = "당신은 ESL(전자 가격표) 시스템 전문 AI 엔지니어입니다. 알람을 분석하고 실용적인 조치를 제안하세요.";
        String prompt = String.format(
            "ESL 장치 알람 분석:\n유형: %s\n심각도: %s\n메시지: %s\n\n" +
            "원인 분석 및 조치 방안을 3줄 이내로 간결하게 제시하세요.",
            alarmType, severity, message
        );

        String result = routeOrFallback(system, prompt);
        return ApiResponse.ok(Map.of("analysis", result, "alarmType", alarmType, "severity", severity));
    }

    /**
     * POS 데이터 AI 분류 — 이상 데이터 자동 감지(provider 라우팅, 실패 시 규칙기반 폴백).
     */
    @PostMapping("/classify-pos")
    public ApiResponse<Map<String, String>> classifyPos(@RequestBody Map<String, Object> body) {
        String productCode = (String) body.getOrDefault("productCode", "");
        String price       = String.valueOf(body.getOrDefault("price", "0"));
        String salePrice   = String.valueOf(body.getOrDefault("salePrice", "0"));

        String system = "당신은 POS 데이터 품질 관리 AI입니다. 가격 데이터의 이상을 감지하세요.";
        String prompt = String.format(
            "POS 가격 데이터 검증:\n상품코드: %s\n정가: %s\n판매가: %s\n\n" +
            "이 데이터가 정상인지 이상(오류/이상값)인지 판단하고, 분류(NORMAL/ABNORMAL)와 이유를 2줄 이내로 제시하세요.",
            productCode, price, salePrice
        );

        String result = routeOrFallback(system, prompt);
        String classification = result.toUpperCase().contains("ABNORMAL") ? "ABNORMAL" : "NORMAL";

        return ApiResponse.ok(Map.of(
            "classification", classification,
            "analysis", result,
            "productCode", productCode
        ));
    }

    /**
     * 일반 AI 채팅 — ESN 운영 관련 질문(provider 라우팅, 실패 시 규칙기반 폴백).
     */
    @PostMapping("/chat")
    public ApiResponse<Map<String, String>> chat(@RequestBody Map<String, String> body) {
        String message = body.getOrDefault("message", "");
        String system = "ESL 전자 가격표 통합 관리 플랫폼 운영 전문가입니다.";
        String result = routeOrFallback(system, message);
        return ApiResponse.ok(Map.of("response", result));
    }

    /**
     * 라우터(Claude↔Ollama) 경유 → degraded 면 기존 OllamaClient.chat 규칙기반 폴백.
     * 시스템 지시는 프롬프트 앞에 병합(단일 user 메시지 계약). 응답은 항상 비어있지 않다.
     */
    private String routeOrFallback(String system, String prompt) {
        String merged = (system == null || system.isBlank()) ? prompt : system + "\n\n" + prompt;
        GenResult r = aiRouter.generate(merged);
        if (!r.degraded() && r.text() != null && !r.text().isBlank()) {
            return r.text();
        }
        // 전 provider 실패 → 기존 규칙기반 폴백(무회귀, 항상 문자열 반환).
        return ollama.chat(prompt, system);
    }
}
