"""
slicer.py — Split multi-shot video output into individual clips.

Uses FFmpeg re-encoding (not stream copy) for frame-accurate cuts.
H.264 keyframe intervals make stream copy inaccurate for 3s shots.
Re-encoding at CRF 18 is visually lossless and takes <5s per clip.
"""

import logging
import subprocess
from pathlib import Path

logger = logging.getLogger(__name__)


def slice_multi_shot_video(
    video_path: Path,
    shot_durations: list[int],
    shot_ids: list[str],
    output_dir: Path,
) -> list[Path]:
    """Split a multi-shot video into individual clips at exact timestamps.

    Args:
        video_path: Path to the multi-shot video (MP4).
        shot_durations: Duration of each shot in seconds (e.g., [3, 5, 4]).
        shot_ids: Corresponding shot IDs (e.g., ["EP001_SH01", "EP001_SH02"]).
        output_dir: Directory to write individual clips.

    Returns:
        List of output clip paths (only successfully created ones).
    """
    if not video_path.exists():
        raise FileNotFoundError(f"Video not found: {video_path}")

    if len(shot_durations) != len(shot_ids):
        raise ValueError(
            f"shot_durations ({len(shot_durations)}) and "
            f"shot_ids ({len(shot_ids)}) must have same length"
        )

    output_dir.mkdir(parents=True, exist_ok=True)
    clips: list[Path] = []
    start_time = 0

    for duration, shot_id in zip(shot_durations, shot_ids):
        output_path = output_dir / f"{shot_id}.mp4"

        cmd = [
            "ffmpeg", "-y",
            "-ss", str(start_time),
            "-i", str(video_path),
            "-t", str(duration),
            "-c:v", "libx264",
            "-crf", "18",
            "-preset", "fast",
            "-c:a", "aac",  # Keep audio
            str(output_path),
        ]

        result = subprocess.run(cmd, capture_output=True, text=True)
        if result.returncode != 0:
            logger.error(
                "FFmpeg slice failed for %s at %ds: %s",
                shot_id, start_time, result.stderr[:300],
            )
        else:
            logger.info("Sliced %s: %ds-%ds → %s", shot_id, start_time, start_time + duration, output_path)
            clips.append(output_path)

        start_time += duration

    return clips


def get_video_duration(video_path: Path) -> float:
    """Get the duration of a video file in seconds using ffprobe."""
    cmd = [
        "ffprobe", "-v", "quiet",
        "-show_entries", "format=duration",
        "-of", "csv=p=0",
        str(video_path),
    ]
    result = subprocess.run(cmd, capture_output=True, text=True)
    if result.returncode != 0:
        logger.warning("ffprobe failed for %s: %s", video_path, result.stderr[:200])
        return 0.0
    try:
        return float(result.stdout.strip())
    except ValueError:
        return 0.0


def validate_slice_durations(
    video_path: Path,
    expected_total: int,
    tolerance: float = 1.0,
) -> dict:
    """Check if video duration matches expected total from shot durations."""
    actual = get_video_duration(video_path)
    drift = abs(actual - expected_total)
    ok = drift <= tolerance

    if not ok:
        logger.warning(
            "Duration drift: expected %ds, got %.1fs (drift: %.1fs)",
            expected_total, actual, drift,
        )

    return {
        "actual_duration": actual,
        "expected_duration": expected_total,
        "drift": drift,
        "ok": ok,
    }
