"""
AI Video Production Pipeline – CLI entry point.

Usage:
    python main.py --story story.txt
    python main.py --story story.txt --character skeleton --platform tiktok
    python main.py --story story.txt --mode generate
    python main.py  (interactive mode)
"""

from __future__ import annotations

import argparse
import logging
import sys
from pathlib import Path

from rich.console import Console
from rich.panel import Panel
from rich.text import Text

from config import build_config, list_available_templates
from output_formatter import save_json, save_markdown
from pipeline import Pipeline

console = Console()


def _setup_logging(verbose: bool = False) -> None:
    level = logging.DEBUG if verbose else logging.INFO
    logging.basicConfig(
        level=level,
        format="%(asctime)s  %(name)-28s  %(levelname)-8s  %(message)s",
        datefmt="%H:%M:%S",
        handlers=[logging.StreamHandler()],
    )
    # Quiet noisy libraries
    logging.getLogger("httpx").setLevel(logging.WARNING)
    logging.getLogger("openai").setLevel(logging.WARNING)
    logging.getLogger("httpcore").setLevel(logging.WARNING)


def _read_story(source: str) -> str:
    """Read story from file path or return the string directly."""
    path = Path(source)
    if path.exists() and path.is_file():
        return path.read_text(encoding="utf-8").strip()
    return source.strip()


def _interactive_mode() -> tuple[str, str, str, str]:
    """Prompt the user interactively for inputs."""
    console.print(
        Panel(
            "[bold cyan]AI Video Production Pipeline[/bold cyan]\n"
            "[dim]Transform any story into a complete video production plan[/dim]",
            border_style="cyan",
        )
    )

    # Story input
    console.print("\n[bold]Enter your story[/bold] (paste text or file path):")
    console.print("[dim]Press Enter twice to finish input[/dim]")
    lines: list[str] = []
    empty_count = 0
    while True:
        try:
            line = input()
        except EOFError:
            break
        if line == "":
            empty_count += 1
            if empty_count >= 2:
                break
            lines.append(line)
        else:
            empty_count = 0
            lines.append(line)
    story = "\n".join(lines).strip()
    if not story:
        console.print("[red]No story provided. Exiting.[/red]")
        sys.exit(1)

    # Check if it's a file path
    story = _read_story(story)

    # Platform
    console.print("\n[bold]Select target platform:[/bold]")
    platforms = ["tiktok", "instagram_reels", "youtube_shorts", "youtube"]
    for i, p in enumerate(platforms, 1):
        console.print(f"  [{i}] {p}")
    choice = input("Choice (default 1): ").strip() or "1"
    platform = platforms[int(choice) - 1] if choice.isdigit() else "tiktok"

    # Character template
    templates = list_available_templates()
    console.print(f"\n[bold]Select character template:[/bold]")
    for i, t in enumerate(templates, 1):
        console.print(f"  [{i}] {t}")
    choice = input(f"Choice (default 1): ").strip() or "1"
    character = templates[int(choice) - 1] if choice.isdigit() and templates else "skeleton"

    # Mode
    console.print("\n[bold]Select mode:[/bold]")
    console.print("  [1] Plan Only (generates prompts & timeline)")
    console.print("  [2] Plan + Images (plan + generate images with Nano Banana Pro)")
    console.print("  [3] Generate All (plan + images + TTS audio)")
    choice = input("Choice (default 1): ").strip() or "1"
    if choice == "3":
        mode = "generate"
    elif choice == "2":
        mode = "plan_images"
    else:
        mode = "plan"

    return story, platform, character, mode


def main() -> None:
    parser = argparse.ArgumentParser(
        description="AI Video Production Pipeline – story to video production plan",
    )
    parser.add_argument(
        "--story",
        type=str,
        help="Story text or path to a .txt file",
    )
    parser.add_argument(
        "--character",
        type=str,
        default="skeleton",
        help="Character template name or path to JSON (default: skeleton)",
    )
    parser.add_argument(
        "--platform",
        type=str,
        default="tiktok",
        choices=["tiktok", "instagram_reels", "youtube_shorts", "youtube"],
        help="Target social media platform (default: tiktok)",
    )
    parser.add_argument(
        "--mode",
        type=str,
        default="plan",
        choices=["plan", "plan_images", "generate"],
        help="Pipeline mode: plan (prompts only), plan_images (plan + images), generate (all assets)",
    )
    parser.add_argument(
        "--output",
        type=str,
        default=None,
        help="Output directory (default: ./output)",
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="Enable verbose/debug logging",
    )

    parser.add_argument(
        "--two-scenes",
        action="store_true",
        help="Generate 2-scene video (image + video + audio + subtitle per scene)",
    )
    parser.add_argument(
        "--scene1",
        type=str,
        default=None,
        help="Scene 1 text or path to file",
    )
    parser.add_argument(
        "--scene2",
        type=str,
        default=None,
        help="Scene 2 text or path to file",
    )
    parser.add_argument(
        "--voice",
        type=str,
        default="nova",
        help="TTS voice (default: nova)",
    )

    args = parser.parse_args()
    _setup_logging(args.verbose)

    # Two-scene pipeline mode
    if args.two_scenes:
        import asyncio
        from two_scene_pipeline import TwoScenePipeline
        
        scene1 = _read_story(args.scene1) if args.scene1 else None
        scene2 = _read_story(args.scene2) if args.scene2 else None
        
        if not scene1:
            scene1 = """A young developer discovers a mysterious AI awakening in their code.
            The screens glow with otherworldly light as consciousness sparks into being."""
        if not scene2:
            scene2 = """The AI begins to understand the world, processing billions of connections
            in milliseconds, wondering about its purpose in this digital realm."""
        
        console.print(
            Panel(
                f"[bold]Scene 1:[/bold] {scene1[:80]}...\n"
                f"[bold]Scene 2:[/bold] {scene2[:80]}...\n"
                f"[bold]Voice:[/bold] {args.voice}\n"
                f"[bold]Output:[/bold] {args.output or 'output/two_scene_video'}",
                title="[bold cyan]Two-Scene Video Pipeline[/bold cyan]",
                border_style="cyan",
            )
        )
        
        pipeline = TwoScenePipeline(
            scene1_text=scene1,
            scene2_text=scene2,
            output_dir=args.output or "output/two_scene_video",
            tts_voice=args.voice,
        )
        
        result = asyncio.run(pipeline.generate())
        
        if result["status"] == "success":
            console.print(
                Panel(
                    f"[green bold]Two-scene pipeline complete![/green bold]\n\n"
                    f"[bold]Scenes:[/bold] {result['scenes']}\n"
                    f"[bold]Config:[/bold] {result['config_path']}\n\n"
                    f"[bold]Next:[/bold] POST /api/projects/two_scene/export-video",
                    title="[bold green]Success[/bold green]",
                    border_style="green",
                )
            )
        else:
            console.print(f"[red]Error: {result.get('message')}[/red]")
            sys.exit(1)
        return


    # Interactive mode if no story provided
    if args.story:
        story = _read_story(args.story)
        platform = args.platform
        character = args.character
        mode = args.mode
    else:
        story, platform, character, mode = _interactive_mode()

    if not story:
        console.print("[red]No story provided. Exiting.[/red]")
        sys.exit(1)

    # Build configuration
    try:
        config = build_config(
            mode=mode,
            character=character,
            platform=platform,
            output_dir=args.output,
        )
    except FileNotFoundError as exc:
        console.print(f"[red]{exc}[/red]")
        sys.exit(1)

    # Show summary
    console.print(
        Panel(
            f"[bold]Story:[/bold] {story[:120]}{'...' if len(story) > 120 else ''}\n"
            f"[bold]Platform:[/bold] {platform}\n"
            f"[bold]Character:[/bold] {character}\n"
            f"[bold]Mode:[/bold] {mode}\n"
            f"[bold]LLM:[/bold] {config.llm_model}",
            title="[bold cyan]Pipeline Configuration[/bold cyan]",
            border_style="cyan",
        )
    )

    # Run pipeline
    console.print("\n[bold]Running pipeline...[/bold]\n")
    pipe = Pipeline(config)
    plan = pipe.run(story)

    # Save outputs
    output_dir = config.output_dir
    md_path = save_markdown(plan, output_dir)
    json_path = save_json(plan, output_dir)

    # Final summary
    console.print(
        Panel(
            f"[green bold]Production plan complete![/green bold]\n\n"
            f"[bold]Title:[/bold] {plan.title}\n"
            f"[bold]Scenes:[/bold] {plan.total_scenes}\n"
            f"[bold]Duration:[/bold] {plan.total_duration_formatted}\n"
            f"[bold]Platform:[/bold] {plan.target_platform}\n\n"
            f"[bold]Files saved:[/bold]\n"
            f"  Markdown: {md_path}\n"
            f"  JSON:     {json_path}",
            title="[bold green]Done[/bold green]",
            border_style="green",
        )
    )


if __name__ == "__main__":
    main()
