#!/usr/bin/env python3
"""Batch TTS generation for DilemmaDash scenarios.

Fetches scenarios from the backend API, generates MP3 audio for each
using a specified voice profile, and saves to a canonical output directory.

Usage:
    python generate_batch.py --voice dark_narrator_v2
    python generate_batch.py --voice dark_narrator_v2 --output-dir /data/audio
    python generate_batch.py --voice dark_narrator_v2 --slug one-ventilator-two-patients
    python generate_batch.py --voice dark_narrator_v2 --dry-run
"""

from __future__ import annotations

import argparse
import sys
import time
from pathlib import Path

import httpx

BACKEND_URL = "http://10.0.0.4:3100"
TTS_URL = "http://localhost:9100"
TIMEOUT = 600.0


def fetch_scenarios(slug: str | None = None) -> list[dict]:
    """Fetch scenarios from the backend API."""
    r = httpx.get(f"{BACKEND_URL}/api/scenarios/tts", timeout=30.0)
    r.raise_for_status()
    scenarios = r.json()
    if slug:
        scenarios = [s for s in scenarios if s["slug"] == slug]
        if not scenarios:
            print(f"Error: scenario '{slug}' not found", file=sys.stderr)
            sys.exit(1)
    return scenarios


def generate_audio(text: str, voice: str) -> bytes:
    """Generate MP3 audio from the TTS service."""
    r = httpx.post(
        f"{TTS_URL}/tts/generate",
        json={"text": text, "voice": voice, "language": "English", "format": "mp3"},
        timeout=TIMEOUT,
    )
    r.raise_for_status()
    return r.content


def main() -> None:
    parser = argparse.ArgumentParser(description="Batch TTS generation for scenarios")
    parser.add_argument("--voice", required=True, help="Voice profile name to use")
    parser.add_argument("--output-dir", default="/data/audio", help="Output directory for MP3s")
    parser.add_argument("--slug", help="Generate only this scenario slug")
    parser.add_argument("--skip-existing", action="store_true", help="Skip if MP3 already exists")
    parser.add_argument("--dry-run", action="store_true", help="List scenarios without generating")
    args = parser.parse_args()

    output_dir = Path(args.output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    # Verify voice exists
    r = httpx.get(f"{TTS_URL}/voices", timeout=10.0)
    r.raise_for_status()
    voices = {v["name"] for v in r.json()}
    if args.voice not in voices:
        print(f"Error: voice '{args.voice}' not found. Available: {sorted(voices)}", file=sys.stderr)
        sys.exit(1)

    scenarios = fetch_scenarios(args.slug)
    print(f"Found {len(scenarios)} scenario(s), voice={args.voice}, output={output_dir}")

    if args.dry_run:
        for s in scenarios:
            out = output_dir / f"{s['slug']}.mp3"
            exists = out.exists()
            print(f"  {'[exists]' if exists else '[new]   '} {s['slug']} — {s['title']}")
        return

    total = len(scenarios)
    skipped = 0
    failed = 0

    for i, s in enumerate(scenarios, 1):
        slug = s["slug"]
        out = output_dir / f"{slug}.mp3"

        if args.skip_existing and out.exists():
            skipped += 1
            print(f"  [{i}/{total}] {slug} — skipped (exists)")
            continue

        text = s.get("bodyVoice", "")
        if not text:
            print(f"  [{i}/{total}] {slug} — skipped (no bodyVoice)")
            skipped += 1
            continue

        print(f"  [{i}/{total}] {slug} — generating...", end="", flush=True)
        t0 = time.time()
        try:
            audio = generate_audio(text, args.voice)
            out.write_bytes(audio)
            elapsed = time.time() - t0
            size_kb = len(audio) / 1024
            print(f" {elapsed:.0f}s, {size_kb:.0f}KB")
        except Exception as e:
            failed += 1
            elapsed = time.time() - t0
            print(f" FAILED ({elapsed:.0f}s): {e}")

    generated = total - skipped - failed
    print(f"\nDone: {generated} generated, {skipped} skipped, {failed} failed")


if __name__ == "__main__":
    main()
