package com.tasteby.service;

import com.tasteby.util.CuisineTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
public class ExtractorService {

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

    private final OciGenAiService genAi;

    private static final String EXTRACT_PROMPT = """
        다음은 유튜브 먹방/맛집 영상의 자막입니다.
        이 영상에서 언급된 모든 식당 정보를 추출하세요.

        규칙:
        - 식당이 없으면 빈 배열 [] 반환
        - 각 식당에 대해 아래 필드를 JSON 배열로 반환
        - 확실하지 않은 정보는 null
        - 추가 설명 없이 JSON만 반환
        - 무조건 한글로 만들어주세요

        필드:
        - name: 식당 이름 (string, 필수)
        - address: 주소 또는 위치 힌트 (string | null)
        - region: 지역을 "나라|시/도|구/군/시" 파이프(|) 구분 형식으로 작성 (string | null)
          - 한국 예시: "한국|서울|강남구", "한국|부산|해운대구", "한국|제주", "한국|강원|강릉시"
          - 해외 예시: "일본|도쿄", "일본|오사카", "싱가포르", "미국|뉴욕", "태국|방콕"
          - 나라는 한글로, 해외 도시도 한글로 표기
        - cuisine_type: 아래 목록에서 가장 적합한 것을 선택 (string, 필수). 반드시 아래 목록 중 하나를 사용:
        %s
        - price_range: 가격대 (예: 1만원대, 2-3만원) (string | null)
        - foods_mentioned: 언급된 대표 메뉴 (string[], 최대 10개, 우선순위 높은 순, 반드시 한글로 작성)
        - evaluation: 평가 내용을 100자 이내로 요약 (string | null)
        - guests: 함께한 게스트 (string[])

        영상 제목: {title}
        자막:
        {transcript}

        JSON 배열:""".formatted(CuisineTypes.CUISINE_LIST_TEXT);

    public ExtractorService(OciGenAiService genAi) {
        this.genAi = genAi;
    }

    public String getPrompt() {
        return EXTRACT_PROMPT;
    }

    public record ExtractionResult(List<Map<String, Object>> restaurants, String rawResponse) {}

    /**
     * Extract restaurant info from a video transcript using LLM.
     */
    @SuppressWarnings("unchecked")
    public ExtractionResult extractRestaurants(String title, String transcript, String customPrompt) {
        // #292 — transcript null/blank 가드 (NPE 방지)
        if (transcript == null || transcript.isBlank()) {
            return new ExtractionResult(List.of(), "");
        }
        // Truncate very long transcripts
        if (transcript.length() > 8000) {
            transcript = transcript.substring(0, 7000) + "\n...(중략)...\n" + transcript.substring(transcript.length() - 1000);
        }

        String template = customPrompt != null ? customPrompt : EXTRACT_PROMPT;
        String prompt = template.replace("{title}", title).replace("{transcript}", transcript);

        try {
            String raw = genAi.chat(prompt, 8192);
            Object result = genAi.parseJson(raw);
            if (result instanceof List<?> list) {
                return new ExtractionResult((List<Map<String, Object>>) list, raw);
            }
            if (result instanceof Map<?, ?> map) {
                return new ExtractionResult(List.of((Map<String, Object>) map), raw);
            }
            return new ExtractionResult(Collections.emptyList(), raw);
        } catch (Exception e) {
            log.error("Restaurant extraction failed: {}", e.getMessage());
            return new ExtractionResult(Collections.emptyList(), "");
        }
    }
}
