"""
vr init command - Initialize a new voice agent project.
"""

import re
from pathlib import Path
from typing import Optional, List

import typer

from vr_cli.utils.utils import (
    console,
    print_success,
    print_error,
    prompt,
)
from ..entities.agent_template import AgentTemplateRepository


def get_template_path() -> Path:
    """Get the path to the templates directory."""
    return Path(__file__).parent.parent / "templates"


def render_template(content: str, **kwargs) -> str:
    """Render a template with the given variables.

    Uses simple {variable} replacement to avoid conflicts with Go/Helm templates
    that use {{ }} syntax.
    """
    for key, value in kwargs.items():
        # Only replace {key} patterns that are not part of {{ }} (Go templates)
        # Match {key} but not {{key}} or {key}}
        pattern = r'(?<!\{)\{' + re.escape(key) + r'\}(?!\})'
        content = re.sub(pattern, str(value), content)

    return content


def get_dest_path(template_rel_path: str) -> str:
    """Convert template path to destination path.

    Handles special cases:
    - 'gitignore' -> '.gitignore'
    - 'vrignore' -> '.vrignore'
    - 'voicerun/' -> '.voicerun/'
    """
    dest = template_rel_path

    # Handle gitignore -> .gitignore
    if dest == "gitignore":
        dest = ".gitignore"

    # Handle vrignore -> .vrignore
    if dest == "vrignore":
        dest = ".vrignore"

    # Handle voicerun/ -> .voicerun/
    if dest.startswith("voicerun/"):
        dest = ".voicerun/" + dest[len("voicerun/"):]

    return dest


def init(
    name: str = typer.Argument(
        None,
        help="Project name. Creates a folder with this name.",
    ),
    yes: bool = typer.Option(
        False,
        "--yes",
        "-y",
        help="Skip prompts and use default values.",
    ),
    force: bool = typer.Option(
        False,
        "--force",
        "-f",
        help="Overwrite existing project files.",
    ),
    template: Optional[str] = typer.Option(
        None,
        "--template",
        "-t",
        help="Initialize from a template (name or ID).",
    ),
    var: Optional[List[str]] = typer.Option(
        None,
        "--var",
        help="Template variable as key=value (can be repeated).",
    ),
):
    """Initialize a new voice agent project with handler and configuration files."""

    if template:
        # Template-based initialization
        repo = AgentTemplateRepository()
        template_entity = repo.get_by_name_or_id(template)

        if not template_entity:
            print_error(f"Template not found: {template}")
            raise typer.Exit(1)

        # Fetch full template (with files from GCS) via getById
        template_entity = repo.get_by_id(template_entity.id)

        # Use name argument or default to template name
        project_name = name or template_entity.name

        # Collect variable values from --var args
        template_vars = {}
        if var:
            for v in var:
                if "=" not in v:
                    print_error(f"Invalid variable format: {v}. Use key=value.")
                    raise typer.Exit(1)
                key, value = v.split("=", 1)
                template_vars[key] = value

        # Prompt for any missing required variables
        variables = template_entity.variables or []
        for variable in variables:
            var_name = variable if isinstance(variable, str) else variable.get("name", "")
            if var_name and var_name not in template_vars:
                if yes:
                    print_error(f"Missing required variable: {var_name}. Use --var {var_name}=value")
                    raise typer.Exit(1)
                template_vars[var_name] = prompt(f"{var_name}")

        # Create project directory
        project_dir = Path.cwd() / project_name

        if project_dir.exists():
            if any(project_dir.iterdir()):
                if not force:
                    print_error(
                        f"Directory '{project_name}' exists and is not empty. "
                        "Use --force to overwrite."
                    )
                    raise typer.Exit(1)
        else:
            project_dir.mkdir(parents=True)

        # Render template files
        created_files = []
        files = template_entity.files or {}

        for file_path, content in files.items():
            # Replace variables in both path and content
            rendered_path = render_template(file_path, **template_vars)
            rendered_content = render_template(content, **template_vars)

            dest_path = project_dir / rendered_path
            dest_path.parent.mkdir(parents=True, exist_ok=True)

            with open(dest_path, "w") as f:
                f.write(rendered_content)

            created_files.append(rendered_path)

        # Print summary
        console.print()
        print_success(f"Project '{project_name}' initialized from template '{template_entity.name}'!")
        console.print()
        console.print("[bold]Created files:[/bold]")
        for file in created_files:
            console.print(f"  [cyan]{file}[/cyan]")

        console.print()
        console.print("[dim]Next steps:[/dim]")
        console.print(f"  1. [cyan]cd {project_name}[/cyan]")
        console.print("  2. Review and customize the generated files")
        console.print("  3. Run [cyan]vr push[/cyan] to push your agent to the server")
        return

    # Default behavior: scaffold from local templates

    # Get project name
    if not name:
        if yes:
            print_error("Project name is required when using --yes")
            raise typer.Exit(1)
        name = prompt("Project name")

    project_name = name

    # Gather additional configuration
    if yes:
        description = ""
    else:
        description = typer.prompt(
            "Description (optional)",
            default="",
            show_default=False,
        )
        console.print()

    # Create project directory
    project_dir = Path.cwd() / project_name

    if project_dir.exists():
        if any(project_dir.iterdir()):
            if not force:
                print_error(
                    f"Directory '{project_name}' exists and is not empty. "
                    "Use --force to overwrite."
                )
                raise typer.Exit(1)
    else:
        project_dir.mkdir(parents=True)

    # Template variables
    template_vars = {
        "project_name": project_name,
        "description": description or f"Voice agent project: {project_name}",
    }

    # Walk templates directory and copy files
    templates_dir = get_template_path()
    created_files = []

    TEMPLATE_EXTENSIONS = {".md", ".py", ".txt", ".yaml", ".yml"}
    TEMPLATE_NAMES = {"gitignore", "vrignore"}
    for template_file in sorted(templates_dir.rglob("*")):
        if template_file.is_dir():
            continue

        # Only process known text template files
        if template_file.suffix not in TEMPLATE_EXTENSIONS and template_file.name not in TEMPLATE_NAMES:
            continue

        # Get relative path from templates dir
        rel_path = template_file.relative_to(templates_dir)

        # Convert to destination path
        dest_rel_path = get_dest_path(str(rel_path))
        dest_path = project_dir / dest_rel_path

        # Create parent directories
        dest_path.parent.mkdir(parents=True, exist_ok=True)

        # Read template content
        try:
            with open(template_file, "r") as f:
                content = f.read()
        except UnicodeDecodeError:
            console.print(f"  [yellow]Skipping non-text file: {rel_path}[/yellow]")
            continue

        # Render template variables
        content = render_template(content, **template_vars)

        # Write to destination
        with open(dest_path, "w") as f:
            f.write(content)

        created_files.append(dest_rel_path)

    # Print summary
    console.print()
    print_success(f"Project '{project_name}' initialized successfully!")
    console.print()
    console.print("[bold]Created files:[/bold]")
    for file in created_files:
        console.print(f"  [cyan]{file}[/cyan]")

    console.print()
    console.print("[dim]Next steps:[/dim]")
    console.print(f"  1. [cyan]cd {project_name}[/cyan]")
    console.print("  2. Edit handler.py to customize your agent")
    console.print("  3. Run [cyan]vr push[/cyan] to push your agent to the server")
