package com.zioinfo.mes.ai.learning;

import com.zioinfo.mes.admin.AuditService;
import com.zioinfo.mes.common.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;

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

/**
 * AI 답변 피드백 수집(👍/👎 + 교정). [GUARDiA-MES]
 *
 * <p>{@code POST /api/ai/feedback} — ① 로컬 DuckDB({@link AiLearningStore}) 적재(오프라인 AI 분석/학습셋)
 * + ② 중앙 guardia-rag {@code /feedback} 전달(통합 학습·평가 게이트). 둘 중 하나가 실패해도 200 을 유지한다.
 *
 * <p>인증: {@code /api/ai/**} 는 SecurityConfig 의 {@code anyRequest().authenticated()} 로 로그인 사용자면
 * 누구나 피드백 가능(관리자 전용 아님). PII/자격증명은 로컬 적재 전 마스킹된다.
 * 보안 불변: 중앙 rag 는 온프레미스 루프백 전용. 외부 전달 없음. 응답에 키/스택트레이스 미포함.
 */
@Slf4j
@RestController
@RequestMapping("/api/ai/feedback")
@RequiredArgsConstructor
public class AiFeedbackController {

    private final AiLearningStore store;
    private final WebClient.Builder webClientBuilder;

    @Value("${guardia.rag.base-url:http://127.0.0.1:8020}")
    private String ragBaseUrl;

    @Value("${guardia.rag.enabled:true}")
    private boolean ragEnabled;

    @PostMapping
    public ApiResponse<Map<String, Object>> feedback(@RequestBody FeedbackRequest req) {
        String actor = AuditService.currentActor();

        // ① 로컬 DuckDB 적재(PII 마스킹은 store 내부에서 수행)
        store.saveFeedback(req.feature(), req.question(), req.answer(),
                req.verdict(), req.correction(), actor);

        // ② 중앙 guardia-rag 전달(fire-and-forget, 실패 무시 — 응답은 항상 200)
        boolean forwarded = forwardToCentralRag(req);

        Map<String, Object> out = new LinkedHashMap<>();
        out.put("stored", store.isEnabled());     // 로컬 DuckDB 적재 가능 여부
        out.put("forwarded", forwarded);          // 중앙 rag 전달 시도 여부
        return ApiResponse.ok(out);
    }

    /** 중앙 guardia-rag /feedback 전달. 미가용/타임아웃/예외는 조용히 무시. */
    private boolean forwardToCentralRag(FeedbackRequest req) {
        if (!ragEnabled) {
            return false;
        }
        try {
            Map<String, Object> body = new LinkedHashMap<>();
            body.put("solution", "mes");
            body.put("feature", req.feature());
            body.put("question", req.question());
            body.put("answer", req.answer());
            body.put("verdict", req.verdict());
            body.put("correction", req.correction());
            webClientBuilder.baseUrl(ragBaseUrl).build()
                    .post().uri("/feedback")
                    .bodyValue(body)
                    .retrieve()
                    .toBodilessEntity()
                    .timeout(Duration.ofSeconds(5))
                    .subscribe(
                            ok -> {},
                            err -> log.debug("중앙 rag /feedback 전달 실패(무시): {}", err.getClass().getSimpleName()));
            return true;
        } catch (Exception e) {
            log.debug("중앙 rag /feedback 전달 예외(무시): {}", e.getClass().getSimpleName());
            return false;
        }
    }

    /** 피드백 요청 — verdict: up/down, correction: 교정문(선택). */
    public record FeedbackRequest(
            String feature,
            String question,
            String answer,
            String verdict,
            String correction) {
    }
}
