#!/usr/bin/env python3
"""
Generate AI voice narration for slides using the 2slides API.
Supports single and multi-speaker modes with 30 voice options.
"""

import os
import sys
import json
import argparse
from typing import Optional, Dict, Any, List


API_BASE_URL = "https://2slides.com/api/v1"

# Available voice options (30 voices)
AVAILABLE_VOICES = [
    "Puck", "Aoede", "Charon", "Kore", "Fenrir", "Phoebe", "Asteria",
    "Luna", "Stella", "Theia", "Helios", "Atlas", "Clio", "Melpomene",
    "Calliope", "Erato", "Euterpe", "Polyhymnia", "Terpsichore", "Thalia",
    "Urania", "Zeus", "Hera", "Poseidon", "Athena", "Apollo", "Artemis",
    "Ares", "Aphrodite", "Hephaestus"
]


def get_api_key() -> str:
    """Get API key from environment variable."""
    api_key = os.environ.get("SLIDES_2SLIDES_API_KEY")
    if not api_key:
        raise ValueError(
            "API key not found. Set SLIDES_2SLIDES_API_KEY environment variable.\n"
            "Get your API key from: https://2slides.com/api"
        )
    return api_key


def generate_narration(
    job_id: str,
    language: str = "Auto",
    voice: str = "Puck",
    multi_speaker: bool = False,
    api_key: Optional[str] = None
) -> Dict[str, Any]:
    """
    Generate AI voice narration for slides.

    Args:
        job_id: Job ID from slide generation (must be UUID format for Nano Banana)
        language: Language for narration (default: "Auto")
            Options: Auto, English, Simplified Chinese, Traditional Chinese, Spanish,
            Arabic, Portuguese, Indonesian, Japanese, Russian, Hindi, French, German,
            Vietnamese, Turkish, Polish, Italian, Korean
        voice: Voice name (default: "Puck")
            Options: Puck, Aoede, Charon, Kore, Fenrir, Phoebe, Asteria, Luna, Stella,
            Theia, Helios, Atlas, Clio, Melpomene, Calliope, Erato, Euterpe, Polyhymnia,
            Terpsichore, Thalia, Urania, Zeus, Hera, Poseidon, Athena, Apollo, Artemis,
            Ares, Aphrodite, Hephaestus
        multi_speaker: Enable multi-speaker mode (default: False)
        api_key: API key (uses env var if not provided)

    Returns:
        Dict with narration generation result

    Notes:
        - Job must be completed before adding narration
        - Cost: 210 credits per page (10 for text, 200 for audio)
        - Processing time: Varies by slide count
    """
    import requests

    if api_key is None:
        api_key = get_api_key()

    if voice not in AVAILABLE_VOICES:
        print(f"Warning: Voice '{voice}' not in known voices list", file=sys.stderr)
        print(f"Available voices: {', '.join(AVAILABLE_VOICES)}", file=sys.stderr)

    headers = {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }

    payload = {
        "jobId": job_id,
        "language": language,
        "voice": voice,
        "multiSpeaker": multi_speaker
    }

    url = f"{API_BASE_URL}/slides/generate-narration"

    print("Generating voice narration...", file=sys.stderr)
    print(f"Voice: {voice}, Multi-speaker: {multi_speaker}", file=sys.stderr)

    # Set reasonable timeout for narration generation
    timeout = 120

    response = requests.post(url, headers=headers, json=payload, timeout=timeout)
    response.raise_for_status()

    result = response.json()

    # Check API response structure
    if not result.get("success"):
        # Common error example:
        # {"error":"Job is not completed","code":"JOB_NOT_COMPLETED",...}
        error_msg = result.get("error", "Unknown error")
        code = result.get("code")
        details = result.get("details")
        extra = f" (code={code})" if code else ""
        raise ValueError(f"API error: {error_msg}{extra}{f' details={details}' if details else ''}")

    # API may return either:
    # - { success:true, data:{...} }
    # - { success:true, jobId:"...", message:"..." }  (no data field)
    data = result.get("data")
    if not data:
        data = {
            "jobId": result.get("jobId") or job_id,
            "status": result.get("status") or "pending",
            "message": result.get("message") or "Narration generation started"
        }

    print("✓ Narration generation started!", file=sys.stderr)
    print(f"  Job ID: {data.get('jobId')}", file=sys.stderr)
    print("Use get_job_status.py to check progress", file=sys.stderr)

    return data


def list_voices():
    """Print available voices."""
    print("Available voices (30 total):")
    print("-" * 40)
    for i, voice in enumerate(AVAILABLE_VOICES, 1):
        print(f"{i:2d}. {voice}")
    print("-" * 40)
    print("\nPopular choices: Puck, Aoede, Charon")


def main():
    parser = argparse.ArgumentParser(
        description="Generate AI voice narration for 2slides presentations",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # List available voices
  %(prog)s --list-voices

  # Generate narration with default voice
  %(prog)s --job-id "abc-123-def-456"

  # Generate with specific voice
  %(prog)s --job-id "abc-123-def-456" --voice "Aoede"

  # Generate with multi-speaker mode
  %(prog)s --job-id "abc-123-def-456" --multi-speaker

  # Generate in Spanish
  %(prog)s --job-id "abc-123-def-456" --language "Spanish" --voice "Charon"

Credit Cost: 210 credits per page (10 for text, 200 for audio)
        """
    )

    parser.add_argument("--job-id", help="Job ID from slide generation (UUID format)")
    parser.add_argument("--language", default="Auto", help="Narration language (default: Auto)")
    parser.add_argument("--voice", default="Puck", help="Voice name (default: Puck)")
    parser.add_argument("--multi-speaker", action="store_true", help="Enable multi-speaker mode")
    parser.add_argument("--list-voices", action="store_true", help="List available voices and exit")

    args = parser.parse_args()

    if args.list_voices:
        list_voices()
        return

    if not args.job_id:
        print("Error: --job-id is required (or use --list-voices)", file=sys.stderr)
        sys.exit(1)

    try:
        result = generate_narration(
            job_id=args.job_id,
            language=args.language,
            voice=args.voice,
            multi_speaker=args.multi_speaker
        )

        print(json.dumps(result, indent=2))

    except Exception as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()
