#!/usr/bin/env python3
"""Local speech-to-text using OpenAI Whisper (runs offline after model download)."""

import json
import sys
import warnings

import click

warnings.filterwarnings("ignore")

MODELS = ["tiny", "tiny.en", "base", "base.en", "small", "small.en",
          "medium", "medium.en", "large-v3", "turbo"]


@click.command()
@click.argument("audio_file", type=click.Path(exists=True))
@click.option("-m", "--model", default="base", type=click.Choice(MODELS), help="Whisper model size")
@click.option("-l", "--language", default=None, help="Language code (auto-detect if omitted)")
@click.option("-t", "--timestamps", is_flag=True, help="Include word-level timestamps")
@click.option("-j", "--json", "as_json", is_flag=True, help="Output as JSON")
@click.option("-q", "--quiet", is_flag=True, help="Suppress progress messages")
def main(audio_file, model, language, timestamps, as_json, quiet):
    """Transcribe audio using OpenAI Whisper (local)."""
    import os
    import time
    
    MAX_FILE_AGE_SECONDS = 300  # 5 minutes - files older than this are suspicious
    
    # Validate file exists and has content
    if not os.path.exists(audio_file):
        click.echo(json.dumps({"error": "file_not_found", "path": audio_file}), err=True)
        sys.exit(1)
    
    file_size = os.path.getsize(audio_file)
    if file_size == 0:
        click.echo(json.dumps({"error": "file_empty", "path": audio_file, "size": 0}), err=True)
        sys.exit(1)
    
    if file_size < 1000:  # Less than 1KB is suspicious
        click.echo(f"Warning: file size suspiciously small ({file_size} bytes)", err=True)
    
    # Check file age - reject stale files
    file_mtime = os.path.getmtime(audio_file)
    file_age = time.time() - file_mtime
    
    if file_age > MAX_FILE_AGE_SECONDS:
        click.echo(json.dumps({"error": "file_stale", "path": audio_file, "age_seconds": int(file_age), "max_age": MAX_FILE_AGE_SECONDS}), err=True)
        sys.exit(1)
    try:
        import whisper
    except ImportError:
        click.echo("Error: openai-whisper not installed", err=True)
        sys.exit(1)

    if not quiet:
        click.echo(f"Loading model: {model}...", err=True)

    try:
        whisper_model = whisper.load_model(model)
    except Exception as e:
        click.echo(f"Error loading model: {e}", err=True)
        sys.exit(1)

    if not quiet:
        click.echo(f"Transcribing: {audio_file}...", err=True)

    try:
        result = whisper_model.transcribe(audio_file, language=language,
                                          word_timestamps=timestamps, verbose=False)
    except Exception as e:
        error_msg = str(e)
        click.echo(json.dumps({"error": "transcription_failed", "details": error_msg}), err=True)
        sys.exit(1)

    text = result["text"].strip()

    if as_json:
        output = {"text": text, "language": result.get("language", "unknown")}
        if timestamps and "segments" in result:
            output["segments"] = [
                {"start": s["start"], "end": s["end"], "text": s["text"],
                 **({"words": s["words"]} if "words" in s else {})}
                for s in result["segments"]
            ]
        click.echo(json.dumps(output, indent=2, ensure_ascii=False))
    else:
        click.echo(text)
        if timestamps and "segments" in result:
            click.echo("\n--- Segments ---", err=True)
            for seg in result["segments"]:
                click.echo(f"  [{seg['start']:.2f}s - {seg['end']:.2f}s]: {seg['text']}", err=True)


if __name__ == "__main__":
    main()
