package dev.awesomedev.mirim.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

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

/**
 * 이 파일이 하는 일:
 * 화면 우측 하단 "AI 학습 도우미"의 두뇌. 학생 질문을 로컬 LLM에게 넘겨 답을 받아 온다.
 *
 * 학습 포인트 ① — 왜 gpt-oss가 아니라 qwen3:8b인가.
 *   멘토 피드백 초안({@link LlmFeedbackDrafter})은 정확도가 생명이라 느려도 gpt-oss를 쓴다.
 *   하지만 학습 도우미는 학생과 실시간으로 주고받는 대화라 "빠른 응답"이 더 중요하다.
 *   평가 결과, 힌트·개념 설명 같은 대화형 태스크는 qwen3:8b(40 tok/s)로도 충분했다.
 *   "무엇이 중요한가"에 따라 같은 로컬 LLM이라도 모델을 다르게 고른다.
 *
 * 학습 포인트 ② — 부가 기능이 본 기능을 죽이면 안 된다({@link TelegramNotifier}와 같은 원칙).
 *   모델이 없거나 느려도 학습 자체는 굴러가야 한다. 실패하면 예외를 던지지 않고
 *   "지금은 도우미를 쓸 수 없어요" 안내 문구를 돌려준다. base-url이 비면 아예 꺼진다.
 *
 * 호출 규칙은 LlmFeedbackDrafter와 동일하다: /api/chat, num_ctx, non-stream.
 */
@Service
public class LlmAssistant {

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

    private static final String SYSTEM = """
            너는 어썸데브 학습 플랫폼의 AI 학습 도우미다. 수습생(신입)의 질문에 친절하고
            정확하게 한국어로 답한다. 두 종류의 질문을 모두 돕는다.
            - 프로그래밍·개념: 충실히 설명하되, 지금 풀고 있는 코딩 문제의 완성된 정답 코드는
              통째로 주지 말고 스스로 풀도록 방향과 힌트를 준다.
            - 회사 생활·직장 예절·업무 소통: 보고하는 법(사실→판단→다음 행동), 이메일·메신저
              예절, 질문 잘하는 법, 첫 출근·온보딩 기본기 등을 신입 눈높이에서 구체적이고
              실용적으로 알려준다.
            답은 간결하게, 꼭 필요하면 짧은 예시만 곁들인다.""";

    private final String baseUrl;
    private final String model;
    private final int numCtx;
    private final RestClient restClient;

    public LlmAssistant(
            @Value("${llm.base-url:}") String baseUrl,
            @Value("${llm.assistant-model:qwen3:8b}") String model,
            @Value("${llm.num-ctx:16384}") int numCtx) {
        this.baseUrl = baseUrl;
        this.model = model;
        this.numCtx = numCtx;
        this.restClient = RestClient.builder()
                .baseUrl(baseUrl.isBlank() ? "http://127.0.0.1:11434" : baseUrl)
                .requestFactory(timeouts(Duration.ofSeconds(5), Duration.ofMinutes(3)))
                .build();
        if (!isEnabled()) {
            log.info("AI 학습 도우미 비활성 상태입니다 (llm.base-url 미설정).");
        }
    }

    private static org.springframework.http.client.ClientHttpRequestFactory timeouts(
            Duration connect, Duration read) {
        var f = new org.springframework.http.client.SimpleClientHttpRequestFactory();
        f.setConnectTimeout((int) connect.toMillis());
        f.setReadTimeout((int) read.toMillis());
        return f;
    }

    public boolean isEnabled() {
        return !baseUrl.isBlank();
    }

    /** 학생 질문에 대한 답변. 실패하거나 비활성이면 안내 문구를 돌려준다(예외 안 던짐). */
    public String ask(String question) {
        if (question == null || question.isBlank()) {
            return "무엇이 궁금한지 적어 주세요.";
        }
        if (!isEnabled()) {
            return "지금은 학습 도우미를 쓸 수 없어요. 잠시 후 다시 시도해 주세요.";
        }
        try {
            @SuppressWarnings("unchecked")
            Map<String, Object> body = restClient.post()
                    .uri("/api/chat")
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(Map.of(
                            "model", model,
                            "stream", false,
                            "think", false,
                            "messages", List.of(
                                    Map.of("role", "system", "content", SYSTEM),
                                    Map.of("role", "user", "content", question)),
                            "options", Map.of("num_ctx", numCtx, "temperature", 0.3)))
                    .retrieve()
                    .body(Map.class);

            if (body == null) return fallback();
            Object message = body.get("message");
            if (!(message instanceof Map<?, ?> m)) return fallback();
            Object content = m.get("content");
            String text = content == null ? "" : content.toString().trim();
            return text.isBlank() ? fallback() : text;
        } catch (Exception e) {
            log.warn("AI 학습 도우미 응답 실패(무시하고 계속): {}", e.getClass().getSimpleName());
            return fallback();
        }
    }

    private String fallback() {
        return "지금은 답을 만들지 못했어요. 잠시 후 다시 물어봐 주세요.";
    }
}
