"""Audio transcription via faster-whisper."""

import logging
import subprocess
import tempfile
from dataclasses import dataclass
from pathlib import Path

logger = logging.getLogger(__name__)


class TranscriptionError(Exception):
    """Error during transcription."""


@dataclass
class TranscriptSegment:
    start: float
    end: float
    text: str


class Transcriber:
    """Transcribes video audio using faster-whisper."""

    def __init__(self, model_name: str = "base"):
        self.model_name = model_name
        self._model = None

    def _load_model(self):
        if self._model is None:
            logger.info("Loading Whisper model '%s'...", self.model_name)
            from faster_whisper import WhisperModel
            self._model = WhisperModel(self.model_name, compute_type="int8")
        return self._model

    def _extract_audio(self, video_path: Path, output_path: Path):
        """Extract audio from video to WAV format."""
        try:
            result = subprocess.run(
                [
                    "ffmpeg", "-i", str(video_path),
                    "-vn", "-acodec", "pcm_s16le",
                    "-ar", "16000", "-ac", "1",
                    "-y", str(output_path),
                ],
                capture_output=True, text=True, timeout=300,
            )
        except FileNotFoundError:
            raise TranscriptionError("ffmpeg not found. Install ffmpeg.")
        except subprocess.TimeoutExpired:
            raise TranscriptionError(f"Audio extraction timed out for {video_path}")

        if result.returncode != 0:
            raise TranscriptionError(f"Audio extraction failed: {result.stderr[:500]}")

    def transcribe(self, video_path: str | Path) -> list[TranscriptSegment]:
        """Transcribe a video file. Returns list of transcript segments."""
        video_path = Path(video_path)
        if not video_path.exists():
            raise TranscriptionError(f"File not found: {video_path}")

        model = self._load_model()

        with tempfile.TemporaryDirectory() as tmpdir:
            audio_path = Path(tmpdir) / "audio.wav"
            logger.info("Extracting audio from %s", video_path.name)
            self._extract_audio(video_path, audio_path)

            if not audio_path.exists() or audio_path.stat().st_size == 0:
                logger.warning("No audio track found in %s", video_path.name)
                return []

            logger.info("Transcribing %s", video_path.name)
            try:
                result_segments, _ = model.transcribe(str(audio_path))
            except Exception as e:
                raise TranscriptionError(f"Whisper transcription failed: {e}")

        segments = []
        for seg in result_segments:
            text = seg.text.strip()
            if text:
                segments.append(TranscriptSegment(
                    start=round(seg.start, 2),
                    end=round(seg.end, 2),
                    text=text,
                ))

        logger.info("Transcribed %d segments from %s", len(segments), video_path.name)
        return segments
