from __future__ import annotations

import argparse
from pathlib import Path

from youtube_cli_agent.orchestrator import ExecutionRequest, Orchestrator
from youtube_cli_agent.tools.audio_download import AudioDownloadTool, YtDlpAudioBackend
from youtube_cli_agent.tools.caption_retrieval import (
    CaptionRetrievalTool,
    HttpCaptionDownloader,
    YtDlpCaptionMetadataBackend,
)
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, YtDlpMetadataBackend
from youtube_cli_agent.tools.search import YouTubeSearchTool, YtDlpSearchBackend
from youtube_cli_agent.tools.transcription import TranscriptionTool, WhisperCliEngine


def build_parser() -> argparse.ArgumentParser:
    parser = argparse.ArgumentParser(
        prog="youtube-agent",
        description="Deterministic YouTube transcript orchestration agent",
    )
    parser.add_argument("query", help="YouTube search query")
    parser.add_argument("--limit", type=int, default=10, help="Search result limit (default: 10)")
    parser.add_argument("--select-count", type=int, default=1, help="How many top-ranked videos to process")
    parser.add_argument(
        "--video-ids",
        default="",
        help="Optional comma-separated video IDs to select deterministically from results",
    )
    parser.add_argument("--output-dir", default="transcripts", help="Markdown output directory")
    parser.add_argument("--audio-cache-dir", default=".cache/audio", help="Audio cache directory")
    parser.add_argument(
        "--preferred-languages",
        default="en,en-US,en-GB,es,es-419",
        help="Comma-separated caption language priority",
    )
    parser.add_argument("--fallback-language", default=None, help="Optional language hint for fallback transcription")
    parser.add_argument("--whisper-model", default="tiny", help="Whisper model name for fallback transcription")
    parser.add_argument(
        "--min-transcript-chars",
        type=int,
        default=80,
        help="Minimum transcript length required for validation",
    )
    parser.add_argument("--debug", action="store_true", help="Enable stack traces for unexpected errors")
    return parser


def main(argv: list[str] | None = None) -> int:
    parser = build_parser()
    args = parser.parse_args(argv)

    selected_video_ids = tuple(
        video_id.strip() for video_id in args.video_ids.split(",") if video_id.strip()
    )
    preferred_languages = tuple(
        lang.strip() for lang in args.preferred_languages.split(",") if lang.strip()
    )

    orchestrator = Orchestrator(
        search_tool=YouTubeSearchTool(backend=YtDlpSearchBackend()),
        metadata_tool=MetadataValidationTool(backend=YtDlpMetadataBackend()),
        caption_tool=CaptionRetrievalTool(
            backend=YtDlpCaptionMetadataBackend(),
            downloader=HttpCaptionDownloader(),
            preferred_languages=preferred_languages,
            min_chars=args.min_transcript_chars,
        ),
        audio_tool=AudioDownloadTool(
            backend=YtDlpAudioBackend(),
            cache_dir=Path(args.audio_cache_dir),
        ),
        transcription_tool=TranscriptionTool(
            engine=WhisperCliEngine(model=args.whisper_model),
            min_chars=args.min_transcript_chars,
        ),
        persistence_tool=MarkdownPersistenceTool(min_transcript_chars=args.min_transcript_chars),
        dedupe_tool=DuplicateCheckerTool(min_transcript_chars=args.min_transcript_chars),
    )

    request = ExecutionRequest(
        query=args.query,
        limit=max(1, args.limit),
        select_count=max(1, args.select_count),
        selected_video_ids=selected_video_ids,
        output_dir=Path(args.output_dir),
        audio_cache_dir=Path(args.audio_cache_dir),
        fallback_language=args.fallback_language,
    )

    try:
        success, report = orchestrator.run(request)
        print(report, end="")
        return 0 if success else 1
    except Exception:
        if args.debug:
            raise
        print("# Execution Report\n\n## Final Status\n**Execution Terminated — Error**\n- Stage: Runtime\n- Error Code: `UNEXPECTED`\n- Reason: Unhandled runtime error. Run with --debug for traceback.")
        return 1


if __name__ == "__main__":
    raise SystemExit(main())
