import hashlib
import mimetypes
import shutil
import subprocess
from pathlib import Path


def sha256_file(path: Path) -> str:
    h = hashlib.sha256()
    with path.open("rb") as f:
        for chunk in iter(lambda: f.read(1024 * 1024), b""):
            h.update(chunk)
    return h.hexdigest()


def allowed_video_file(filename: str) -> bool:
    return Path(filename).suffix.lower() in {".mp4", ".mov", ".webm"}


def probe_video(path: Path) -> dict:
    meta = {"duration_sec": None, "width": None, "height": None, "fps": None, "aspect_ratio": None}
    try:
        data = subprocess.check_output([
            "ffprobe", "-v", "error", "-select_streams", "v:0",
            "-show_entries", "stream=width,height,r_frame_rate:format=duration",
            "-of", "json", str(path)
        ], text=True)
        import json
        parsed = json.loads(data)
        stream = (parsed.get("streams") or [{}])[0]
        fmt = parsed.get("format") or {}
        meta["duration_sec"] = float(fmt["duration"]) if fmt.get("duration") else None
        meta["width"] = stream.get("width")
        meta["height"] = stream.get("height")
        rate = stream.get("r_frame_rate") or "0/1"
        num, den = [float(x) for x in rate.split("/")]
        meta["fps"] = round(num / den, 3) if den else None
        if meta["width"] and meta["height"]:
            meta["aspect_ratio"] = f"{meta['width']}:{meta['height']}"
    except Exception:
        pass
    return meta


def generate_thumbnail(video_path: Path, thumbnail_path: Path) -> None:
    thumbnail_path.parent.mkdir(parents=True, exist_ok=True)
    try:
        subprocess.check_call([
            "ffmpeg", "-y", "-hide_banner", "-loglevel", "error", "-ss", "00:00:00.25",
            "-i", str(video_path), "-frames:v", "1", str(thumbnail_path)
        ])
    except Exception:
        # Keep MVP robust even when ffmpeg cannot decode a test fixture.
        thumbnail_path.write_bytes(b"")


def copy_video_to_processed(source: Path, dest: Path) -> dict:
    dest.parent.mkdir(parents=True, exist_ok=True)
    shutil.copy2(source, dest)
    checksum = sha256_file(dest)
    mime_type = mimetypes.guess_type(dest.name)[0] or "application/octet-stream"
    meta = probe_video(dest)
    return {"checksum": checksum, "file_size": dest.stat().st_size, "mime_type": mime_type, **meta}
