#!/usr/bin/env python3
from __future__ import annotations

import os
import sys

from _media_utils import (
    DEFAULT_CLIP_FORMAT,
    die,
    format_seconds,
    parse_non_negative_float,
    require_command,
    resolve_ytdlp_urls,
    run_passthrough,
    timestamp_to_seconds,
)

USAGE = """\
Usage:
  download-clip.py [--dry-run] <youtube-url> <start> <end|+duration> <output.mp4>

Examples:
  download-clip.py "https://www.youtube.com/watch?v=FXnC79xdnXQ" "50:00" "51:20" "clip.mp4"
  download-clip.py "https://www.youtube.com/watch?v=FXnC79xdnXQ" "50:00" "+80" "clip.mp4"

Environment:
  PREROLL_SECONDS  Seconds of lead-in to keep before the requested start. Default: 5.5
  POSTROLL_SECONDS Seconds of tail to keep after the requested end. Default: same as PREROLL_SECONDS
  YTDLP_FORMAT     yt-dlp format selector. Default prefers MP4-compatible streams.
  YTDLP_JS_RUNTIMES Override yt-dlp JS runtimes. Default: auto-use node for YouTube when available.
  YTDLP_EXTRACTOR_ARGS Override yt-dlp extractor args. Default for YouTube: player_client=ios,android
  YTDLP_COOKIES_FROM_BROWSER Browser profile for yt-dlp cookies, if needed.
  YTDLP_COOKIES    Path to a cookies.txt file, if needed.
  YTDLP_EXTRA_ARGS Extra raw yt-dlp args split with shell rules.
"""


def parse_args(argv: list[str]) -> tuple[bool, str, str, str, str]:
    dry_run = False
    if argv and argv[0] == "--dry-run":
        dry_run = True
        argv = argv[1:]

    if len(argv) != 4:
        print(USAGE.rstrip())
        raise SystemExit(1)

    return dry_run, argv[0], argv[1], argv[2], argv[3]


def main(argv: list[str]) -> int:
    dry_run, url, start_arg, end_or_duration_arg, output_file = parse_args(argv)

    try:
        start_seconds = timestamp_to_seconds(start_arg)
    except ValueError as exc:
        die(str(exc))

    try:
        preroll = parse_non_negative_float(os.getenv("PREROLL_SECONDS", "5.5"), "PREROLL_SECONDS")
        postroll = parse_non_negative_float(
            os.getenv("POSTROLL_SECONDS", str(preroll)),
            "POSTROLL_SECONDS",
        )
    except ValueError as exc:
        die(str(exc))

    try:
        if end_or_duration_arg.startswith("+"):
            duration_seconds = timestamp_to_seconds(end_or_duration_arg[1:])
            end_seconds = start_seconds + duration_seconds
        else:
            end_seconds = timestamp_to_seconds(end_or_duration_arg)
            duration_seconds = end_seconds - start_seconds
    except ValueError as exc:
        die(str(exc))

    if duration_seconds <= 0:
        die("clip duration must be positive")

    seek_from_seconds = max(start_seconds - preroll, 0.0)
    leading_padding_seconds = start_seconds - seek_from_seconds
    output_duration_seconds = duration_seconds + leading_padding_seconds + postroll

    if dry_run:
        print(f"url={url}")
        print(f"start_seconds={format_seconds(start_seconds)}")
        print(f"end_seconds={format_seconds(end_seconds)}")
        print(f"duration_seconds={format_seconds(duration_seconds)}")
        print(f"seek_from_seconds={format_seconds(seek_from_seconds)}")
        print(f"leading_padding_seconds={format_seconds(leading_padding_seconds)}")
        print(f"postroll_seconds={format_seconds(postroll)}")
        print(f"output_duration_seconds={format_seconds(output_duration_seconds)}")
        print(f"output_file={output_file}")
        return 0

    require_command("yt-dlp")
    require_command("ffmpeg")

    format_selector = os.getenv("YTDLP_FORMAT", DEFAULT_CLIP_FORMAT)
    urls = resolve_ytdlp_urls(url, format_selector)
    if not urls:
        die("yt-dlp did not return any stream URLs")

    ffmpeg_args = ["ffmpeg"]
    if len(urls) >= 2:
        ffmpeg_args.extend(
            [
                "-ss",
                format_seconds(seek_from_seconds),
                "-i",
                urls[0],
                "-ss",
                format_seconds(seek_from_seconds),
                "-i",
                urls[1],
                "-map",
                "0:v",
                "-map",
                "1:a",
                "-c",
                "copy",
                "-copyinkf",
                "-avoid_negative_ts",
                "make_zero",
                "-movflags",
                "+faststart",
                "-t",
                format_seconds(output_duration_seconds),
                output_file,
            ]
        )
    else:
        ffmpeg_args.extend(
            [
                "-ss",
                format_seconds(seek_from_seconds),
                "-i",
                urls[0],
                "-c",
                "copy",
                "-copyinkf",
                "-avoid_negative_ts",
                "make_zero",
                "-movflags",
                "+faststart",
                "-t",
                format_seconds(output_duration_seconds),
                output_file,
            ]
        )

    run_passthrough(ffmpeg_args)
    return 0


if __name__ == "__main__":
    raise SystemExit(main(sys.argv[1:]))
