from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path

from youtube_cli_agent.models import VideoMetadata
from youtube_cli_agent.orchestrator import ExecutionRequest, Orchestrator
from youtube_cli_agent.tools.audio_download import AudioDownloadTool
from youtube_cli_agent.tools.caption_retrieval import CaptionRetrievalTool
from youtube_cli_agent.tools.dedupe import DuplicateCheckerTool
from youtube_cli_agent.tools.markdown_persistence import MarkdownPersistenceTool
from youtube_cli_agent.tools.metadata_validation import MetadataValidationTool
from youtube_cli_agent.tools.search import YouTubeSearchTool
from youtube_cli_agent.tools.transcription import TranscriptionTool


@dataclass
class FakeSearchBackend:
    def search(self, query: str, limit: int) -> list[dict]:
        return [
            {
                "id": "vid1",
                "title": "Webflow Automation Basics",
                "channel": "Builder",
                "url": "https://www.youtube.com/watch?v=vid1",
                "duration": 240,
                "upload_date": "20250110",
                "description": "desc",
            }
        ]


@dataclass
class FakeMetadataBackend:
    def fetch(self, video_url: str) -> dict:
        return {
            "id": "vid1",
            "title": "Webflow Automation Basics",
            "channel": "Builder",
            "webpage_url": "https://www.youtube.com/watch?v=vid1",
            "upload_date": "20250110",
            "duration": 240,
            "description": "desc",
        }


@dataclass
class FakeCaptionBackend:
    def fetch(self, video_url: str, mode: str) -> dict:
        return {
            "subtitles": {
                "en": [{"ext": "vtt", "url": "https://example.test/vid1.vtt"}],
            },
            "automatic_captions": {},
        }


@dataclass
class FakeCaptionDownloader:
    def fetch(self, url: str) -> bytes:
        return (
            "WEBVTT\n\n00:00:00.000 --> 00:00:05.000\n"
            "This deterministic caption transcript is long enough to satisfy validation rules."
        ).encode("utf-8")


@dataclass
class FakeAudioBackend:
    call_count: int = 0

    def download(self, video_url: str, output_template: str) -> None:
        self.call_count += 1


@dataclass
class FakeTranscriptionEngine:
    call_count: int = 0

    def transcribe(self, audio_path: Path, language: str | None = None) -> str:
        self.call_count += 1
        return "Fallback transcript that should never run in this caption-first test."


def test_full_pipeline_caption_first_and_idempotent(tmp_path: Path) -> None:
    audio_backend = FakeAudioBackend()
    transcription_engine = FakeTranscriptionEngine()

    orchestrator = Orchestrator(
        search_tool=YouTubeSearchTool(backend=FakeSearchBackend()),
        metadata_tool=MetadataValidationTool(backend=FakeMetadataBackend()),
        caption_tool=CaptionRetrievalTool(
            backend=FakeCaptionBackend(),
            downloader=FakeCaptionDownloader(),
            min_chars=20,
        ),
        audio_tool=AudioDownloadTool(backend=audio_backend, cache_dir=tmp_path / "cache"),
        transcription_tool=TranscriptionTool(engine=transcription_engine, min_chars=20),
        persistence_tool=MarkdownPersistenceTool(min_transcript_chars=20),
        dedupe_tool=DuplicateCheckerTool(min_transcript_chars=20),
    )

    request = ExecutionRequest(
        query="webflow automation",
        output_dir=tmp_path / "out",
        audio_cache_dir=tmp_path / "cache",
    )

    success_1, report_1 = orchestrator.run(request)
    success_2, report_2 = orchestrator.run(request)

    assert success_1 is True
    assert "Execution Complete — Success" in report_1
    assert success_2 is True
    assert "Skipped — Transcript already exists and is valid." in report_2
    assert audio_backend.call_count == 0
    assert transcription_engine.call_count == 0

    outputs = list((tmp_path / "out").glob("*.md"))
    assert len(outputs) == 1
    content = outputs[0].read_text(encoding="utf-8")
    assert "- Transcript Source: Official Caption" in content
