"""transcriber 모듈 테스트 (TDD)"""

from unittest.mock import MagicMock, patch

import pytest

from youtube_pipeline.transcriber import (
    TranscriptResult,
    _parse_innertube_transcript,
    fetch_whisper_transcription,
    fetch_youtube_captions,
    make_title_description_fallback,
    transcribe,
)


class TestTranscriptResult:
    def test_dataclass_fields(self):
        result = TranscriptResult(text="test", source="youtube_caption", language="ko")
        assert result.text == "test"
        assert result.source == "youtube_caption"
        assert result.language == "ko"

    def test_optional_fields_default_none(self):
        result = TranscriptResult(text="test", source="whisper_stt")
        assert result.language is None
        assert result.caption_type is None


class TestMakeTitleDescriptionFallback:
    def test_creates_fallback_text(self):
        result = make_title_description_fallback("테스트 제목", "테스트 설명")
        assert result.source == "title_description"
        assert "테스트 제목" in result.text
        assert "테스트 설명" in result.text


class TestFetchYoutubeCaptions:
    @patch("youtube_pipeline.transcriber.requests.post")
    def test_returns_none_on_failure(self, mock_post):
        mock_post.side_effect = Exception("network error")
        result = fetch_youtube_captions("test_id")
        assert result is None

    @patch("youtube_pipeline.transcriber.requests.post")
    def test_returns_none_on_empty_response(self, mock_post):
        mock_resp = MagicMock()
        mock_resp.status_code = 200
        mock_resp.json.return_value = {}
        mock_post.return_value = mock_resp
        result = fetch_youtube_captions("test_id")
        assert result is None


class TestFetchWhisperTranscription:
    @patch("youtube_pipeline.transcriber.requests.post")
    def test_success(self, mock_post):
        mock_resp = MagicMock()
        mock_resp.status_code = 200
        mock_resp.json.return_value = {
            "text": "전사된 텍스트",
            "source": "whisper_local_ytdlp",
        }
        mock_post.return_value = mock_resp
        result = fetch_whisper_transcription("test_id")
        assert result is not None
        assert result.text == "전사된 텍스트"
        assert result.source == "whisper_stt"

    @patch("youtube_pipeline.transcriber.requests.post")
    def test_failure_returns_none(self, mock_post):
        mock_post.side_effect = Exception("connection refused")
        result = fetch_whisper_transcription("test_id")
        assert result is None


class TestTranscribe:
    @patch("youtube_pipeline.transcriber.fetch_whisper_transcription")
    @patch("youtube_pipeline.transcriber.fetch_youtube_captions")
    def test_youtube_caption_priority(self, mock_captions, mock_whisper):
        mock_captions.return_value = TranscriptResult(
            text="자막 텍스트", source="youtube_caption", language="ko"
        )
        result = transcribe("vid1", "제목", "설명")
        assert result.source == "youtube_caption"
        mock_whisper.assert_not_called()

    @patch("youtube_pipeline.transcriber.fetch_whisper_transcription")
    @patch("youtube_pipeline.transcriber.fetch_youtube_captions")
    def test_whisper_fallback(self, mock_captions, mock_whisper):
        mock_captions.return_value = None
        mock_whisper.return_value = TranscriptResult(
            text="Whisper 전사", source="whisper_stt"
        )
        result = transcribe("vid1", "제목", "설명")
        assert result.source == "whisper_stt"

    @patch("youtube_pipeline.transcriber.fetch_whisper_transcription")
    @patch("youtube_pipeline.transcriber.fetch_youtube_captions")
    def test_title_description_fallback(self, mock_captions, mock_whisper):
        mock_captions.return_value = None
        mock_whisper.return_value = None
        result = transcribe("vid1", "제목", "설명")
        assert result.source == "title_description"
        assert "제목" in result.text


class TestParseInnertubeTranscript:
    def test_empty_data_returns_none(self):
        assert _parse_innertube_transcript({}) is None

    def test_parses_cue_groups(self):
        data = {
            "actions": [
                {
                    "updateEngagementPanelAction": {
                        "content": {
                            "transcriptRenderer": {
                                "body": {
                                    "transcriptBodyRenderer": {
                                        "cueGroups": [
                                            {
                                                "transcriptCueGroupRenderer": {
                                                    "cues": [
                                                        {
                                                            "transcriptCueRenderer": {
                                                                "cue": {
                                                                    "simpleText": "안녕하세요"
                                                                }
                                                            }
                                                        }
                                                    ]
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            ]
        }
        result = _parse_innertube_transcript(data)
        assert result == "안녕하세요"
