package com.hlab.yanalyst.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hlab.yanalyst.domain.production.dto.ScriptResponseDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpStatusCodeException;
import org.springframework.web.client.RestTemplate;
import java.util.List;
import java.util.Map;
/**
* Gemini(무료 티어)로 유튜브 URL을 직접 보내 화면에 박힌 자막을 추출·한국어 번역해 세그먼트로 받는다.
* 음성은 Whisper(정밀 타임스탬프)가 담당하므로 여기선 화면 자막만 다룬다.
* 타임스탬프는 Gemini 특성상 ~1초 근사.
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class GeminiSubtitleService {
private static final String PROMPT =
"이 영상을 처음부터 끝까지 분석해서, 화면에 표시되는(영상에 박힌) 모든 자막을 빠짐없이 추출하세요. "
+ "음성/말소리는 무시하고 화면의 글자만 대상으로 합니다. "
+ "각 자막이 화면에 나타나는 시작 시각과 사라지는 끝 시각을 '영상 시작 기준 초'로 최대한 정확히 적으세요(예: 0, 2.5, 8.1). "
+ "중요: 모든 항목의 시간을 0으로 두지 마세요. 자막이 바뀌는 순서대로 start 가 증가해야 합니다. "
+ "각 자막의 화면 원문(그대로)과 한국어 번역을 함께 주세요. "
+ "JSON 배열로만 출력: [{\"start\": 시작초, \"end\": 끝초, \"original\": \"화면 원문 그대로\", \"text\": \"한국어 번역\"}]. "
+ "original 은 화면에 보이는 원문 그대로(번역하지 말 것). "
+ "text 는 그 원문을 반드시 '한국어'로 번역한 결과입니다 — 영어가 아니라 한국어로 쓰세요. "
+ "화면 자막이 전혀 없으면 빈 배열 [].";
private final RestTemplate geminiRestTemplate;
private final ObjectMapper objectMapper;
@Value("${gemini.api-key:}")
private String apiKey;
@Value("${gemini.model:gemini-2.5-flash}")
private String model;
/**
* 유튜브 영상의 화면 자막을 한국어 세그먼트로 반환.
* Gemini 영상이해는 비결정적이라 빈 결과가 나올 수 있어, 0개면 최대 3회 재시도한다(에러는 즉시 전파).
*/
public List fetchKoreanScreenSubtitles(String videoId) {
for (int attempt = 1; attempt <= 3; attempt++) {
List segs = callGeminiOnce(videoId);
if (!segs.isEmpty()) return segs;
log.info("Gemini 화면자막 0개(video {}, {}/3) — 재시도", videoId, attempt);
}
return List.of();
}
/** Gemini 단일 호출(화면 자막 → 한국어 세그먼트). HTTP/키 오류는 예외로 전파, 정상이면 세그먼트(빈 가능). */
private List callGeminiOnce(String videoId) {
String key = sanitizeApiKey(apiKey);
if (key.isEmpty()) {
throw new IllegalArgumentException("GEMINI_API_KEY 가 설정되지 않았습니다.");
}
String videoUrl = "https://www.youtube.com/watch?v=" + videoId;
String apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/"
+ model + ":generateContent?key=" + key;
log.info("Requesting Gemini screen-subtitles for video {} (model={})", videoId, model);
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity