"""Captions: word-timestamped whisper transcription of clip slices."""
import subprocess
import threading
import uuid

from fastapi import APIRouter, HTTPException

from clipshelf.config import JOBS
from clipshelf.routers.editor_common import resolve_media

router = APIRouter(tags=["editor"])

_whisper = None
_whisper_lock = threading.Lock()


@router.post("/api/editor/whisper")
def whisper_words(body: dict):
    """Word-timestamped transcription of a clip slice — exact karaoke
    captions. Needs the optional faster-whisper install; GPU if available,
    CPU otherwise (slower but fine for clip-length audio)."""
    global _whisper
    try:
        from faster_whisper import WhisperModel
    except ImportError:
        raise HTTPException(503, "captions need faster-whisper: pip install faster-whisper")
    src = body.get("src", "")
    t0 = max(0.0, float(body.get("in", 0)))
    dur = min(max(0.5, float(body.get("dur", 30))), 300)
    path = resolve_media(src)
    with _whisper_lock:
        if _whisper is None:
            try:
                _whisper = WhisperModel("base.en", device="cuda", compute_type="int8_float16")
            except Exception:
                _whisper = WhisperModel("base.en", device="cpu", compute_type="int8")
        wav = JOBS / f"wh-{uuid.uuid4().hex[:8]}.wav"
        try:
            subprocess.run(["ffmpeg", "-y", "-ss", f"{t0:.3f}", "-t", f"{dur:.3f}",
                            "-i", path, "-ar", "16000", "-ac", "1", str(wav)],
                           check=True, capture_output=True, timeout=300)
            segs, _info = _whisper.transcribe(str(wav), word_timestamps=True, vad_filter=True)
            words = []
            for s in segs:
                for w in (s.words or []):
                    words.append({"t": round(w.start, 2),
                                  "dur": round(max(0.15, w.end - w.start), 2),
                                  "text": w.word.strip()})
            return {"words": words}
        finally:
            wav.unlink(missing_ok=True)


@router.get("/api/editor/captions")
def captions(src: str):
    """Transcript-store captions for a VOD source: the background worker's
    segments, in clip-file seconds. Whisper (word-exact) is still the
    preferred path; this is the fast fallback."""
    from urllib.parse import unquote
    from clipshelf import db
    src = unquote(src)
    if not src.startswith("/vod_media/"):
        return {"captions": [], "note": "no transcript for this source — use whisper captions"}
    fname = src[len("/vod_media/"):]
    conn = db.connect()
    try:
        vod = conn.execute("SELECT id FROM vods WHERE filename = ?", (fname,)).fetchone()
        if not vod:
            return {"captions": [], "note": "unknown vod — use whisper captions"}
        rows = conn.execute(
            "SELECT t_ms, dur_ms, text FROM transcript_fts WHERE vod_id = ? ORDER BY t_ms",
            (vod["id"],)).fetchall()
    finally:
        conn.close()
    return {"captions": [{"t": r["t_ms"] / 1000, "dur": max(0.4, r["dur_ms"] / 1000),
                          "text": r["text"]} for r in rows],
            "note": None if rows else "no transcript yet — use whisper captions"}
