"""3-tier 전사: YouTube 자막 → Whisper STT → 제목+설명 fallback"""

import base64
import logging
from dataclasses import dataclass
from typing import Optional

import requests

from . import config

logger = logging.getLogger(__name__)


@dataclass
class TranscriptResult:
    text: str
    source: str  # 'youtube_caption' | 'whisper_stt' | 'title_description'
    language: Optional[str] = None
    caption_type: Optional[str] = None  # 'manual' | 'auto-generated'


# ---------------------------------------------------------------------------
# 내부 유틸
# ---------------------------------------------------------------------------


def _build_transcript_params(video_id: str) -> str:
    """InnerTube get_transcript API용 params 생성 (protobuf-style 인코딩)

    field 1 (params): embedded message
      field 1 (video_id): string  →  \x0a <len> <video_id bytes>
    outer: \x0a <inner_len> <inner>
    최종적으로 base64url 인코딩하여 반환.
    """
    video_id_bytes = video_id.encode("utf-8")
    # inner: field 1, type 2 (length-delimited) = tag 0x0a
    inner = b"\x0a" + bytes([len(video_id_bytes)]) + video_id_bytes
    # outer: field 1, type 2 = tag 0x0a
    outer = b"\x0a" + bytes([len(inner)]) + inner
    return base64.b64encode(outer).decode("utf-8")


def _parse_innertube_transcript(data: dict) -> Optional[str]:
    """InnerTube 응답에서 자막 텍스트 추출"""
    try:
        actions = data.get("actions", [])
        for action in actions:
            update = action.get("updateEngagementPanelAction", {})
            content = update.get("content", {})
            transcript_renderer = content.get("transcriptRenderer", {})
            body = transcript_renderer.get("body", {})
            segment_list = body.get("transcriptBodyRenderer", {}).get("cueGroups", [])

            if segment_list:
                texts: list[str] = []
                for group in segment_list:
                    cues = group.get("transcriptCueGroupRenderer", {}).get("cues", [])
                    for cue in cues:
                        cue_text = (
                            cue.get("transcriptCueRenderer", {})
                            .get("cue", {})
                            .get("simpleText", "")
                        )
                        if cue_text:
                            texts.append(cue_text)
                if texts:
                    return "\n".join(texts)
    except Exception:
        pass
    return None


# ---------------------------------------------------------------------------
# 공개 API
# ---------------------------------------------------------------------------


def fetch_youtube_captions(video_id: str) -> Optional[TranscriptResult]:
    """YouTube InnerTube API로 자막 추출 시도 (WEB → TVHTML5 fallback)"""
    try:
        params = _build_transcript_params(video_id)

        # 1차 시도: WEB 클라이언트
        resp = requests.post(
            "https://www.youtube.com/youtubei/v1/get_transcript",
            json={
                "context": {
                    "client": {
                        "clientName": "WEB",
                        "clientVersion": "2.20240101",
                    }
                },
                "params": params,
            },
            headers={"Content-Type": "application/json"},
            timeout=15,
        )
        if resp.status_code == 200:
            text = _parse_innertube_transcript(resp.json())
            if text:
                return TranscriptResult(
                    text=text, source="youtube_caption", language="ko"
                )

        # 2차 시도: TVHTML5 클라이언트
        resp2 = requests.post(
            "https://www.youtube.com/youtubei/v1/get_transcript",
            json={
                "context": {
                    "client": {
                        "clientName": "TVHTML5",
                        "clientVersion": "7.20240101",
                    }
                },
                "params": params,
            },
            headers={"Content-Type": "application/json"},
            timeout=15,
        )
        if resp2.status_code == 200:
            text2 = _parse_innertube_transcript(resp2.json())
            if text2:
                return TranscriptResult(
                    text=text2, source="youtube_caption", language="ko"
                )
    except Exception as e:
        logger.warning("YouTube 자막 추출 실패: %s", e)
    return None


def fetch_whisper_transcription(video_id: str) -> Optional[TranscriptResult]:
    """Whisper GPU 서비스로 전사 (localhost:8200/v1/youtube-transcribe)"""
    try:
        resp = requests.post(
            config.WHISPER_TRANSCRIBE_ENDPOINT,
            json={"video_id": video_id, "language": "ko"},
            timeout=600,  # 긴 영상 처리 대비
        )
        if resp.status_code == 200:
            data = resp.json()
            text = data.get("text", "")
            if text:
                return TranscriptResult(text=text, source="whisper_stt")
    except Exception as e:
        logger.warning("Whisper 전사 실패: %s", e)
    return None


def make_title_description_fallback(title: str, description: str) -> TranscriptResult:
    """제목+설명 fallback (품질 주의 대상)"""
    text = f"영상 제목: {title}\n\n영상 설명:\n{description}"
    return TranscriptResult(text=text, source="title_description")


def transcribe(video_id: str, title: str, description: str) -> TranscriptResult:
    """3-tier 전사 오케스트레이터

    1순위: YouTube 자막 (InnerTube API)
    2순위: Whisper STT (yt-dlp → GPU 전사)
    3순위: 제목+설명 fallback
    """
    # 1순위: YouTube 자막
    result = fetch_youtube_captions(video_id)
    if result:
        logger.info("자막 추출 성공 (YouTube caption): %d자", len(result.text))
        return result

    # 2순위: Whisper STT
    result = fetch_whisper_transcription(video_id)
    if result:
        logger.info("Whisper 전사 성공: %d자", len(result.text))
        return result

    # 3순위: 제목+설명 fallback
    logger.warning("자막/STT 모두 실패 — 제목+설명 fallback")
    return make_title_description_fallback(title, description)
