"""
vr render command - Render templates using Helm and display the output.
"""

from pathlib import Path
from typing import List, Optional

import typer
import yaml

from vr_cli.utils.utils import console, print_error, print_info
from vr_cli.utils.helm import (
    require_helm,
    render_templates,
    HelmError,
)
from vr_cli.commands.validate import (
    ValidationResult,
    validate_voicerun_dir,
    validate_agent_yaml,
)


def parse_set_values(set_args: List[str]) -> dict:
    """Parse --set key=value arguments into a dictionary."""
    result = {}
    for arg in set_args:
        if "=" not in arg:
            raise typer.BadParameter(f"Invalid --set format: {arg}. Use key=value")
        key, value = arg.split("=", 1)
        result[key.strip()] = value.strip()
    return result


def validate_rendered_docs(docs: List[dict], result: ValidationResult):
    """Validate rendered documents."""
    allowed_spec_keys = {
        "env",           # Environment variables
        "stt",           # Speech-to-text config
        "recording",     # Recording settings
        "errorFallback", # Error fallback settings
        "startupAudio",  # Startup audio settings
        "webhook",       # Webhook settings
        "region",        # Execution region
        "tracing",       # Tracing enabled
    }

    for doc in docs:
        kind = doc.get("kind")
        if not kind:
            result.add_fail("rendered template has kind", "Missing 'kind' field")
            continue

        if kind != "Deployment":
            result.add_fail(f"rendered template valid kind", f"Unknown kind: {kind}. Only 'Deployment' is supported.")
            continue

        name = doc.get("metadata", {}).get("name", "unknown")

        # Validate Deployment spec only has allowed keys
        spec = doc.get("spec", {})
        invalid_keys = set(spec.keys()) - allowed_spec_keys
        if invalid_keys:
            result.add_fail(
                f"{kind}/{name} spec valid",
                f"Invalid spec fields: {', '.join(invalid_keys)}. Only {', '.join(sorted(allowed_spec_keys))} are allowed."
            )
            continue

        result.add_pass(f"rendered {kind}/{name}")


def render(
    values: Optional[Path] = typer.Option(
        None,
        "--values",
        "-f",
        help="Path to values file.",
        exists=True,
        resolve_path=True,
    ),
    set_value: Optional[List[str]] = typer.Option(
        None,
        "--set",
        "-s",
        help="Set a value (can be used multiple times). Format: key=value",
    ),
    output: Optional[str] = typer.Option(
        None,
        "--output",
        "-o",
        help="Output format: yaml (default) or json.",
    ),
    quiet: bool = typer.Option(
        False,
        "--quiet",
        "-q",
        help="Only output rendered templates, no validation messages.",
    ),
):
    """Render templates using Helm and display the output."""
    project_dir = Path.cwd()
    voicerun_dir = project_dir / ".voicerun"

    if not voicerun_dir.exists():
        print_error("Not a voicerun project (.voicerun directory not found)")
        print_info("Run 'vr init' to create a new project")
        raise typer.Exit(1)

    if not require_helm():
        raise typer.Exit(1)

    # Parse --set values
    set_values = {}
    if set_value:
        try:
            set_values = parse_set_values(set_value)
        except typer.BadParameter as e:
            print_error(str(e))
            raise typer.Exit(1)

    output_format = output or "yaml"
    if output_format not in ("yaml", "json"):
        print_error(f"Invalid output format: {output_format}")
        print_info("Supported formats: yaml, json")
        raise typer.Exit(1)

    # Run validation
    result = ValidationResult()
    validate_voicerun_dir(project_dir, result)
    validate_agent_yaml(project_dir, result)

    try:
        rendered_docs = render_templates(
            project_dir,
            values_file=values,
            set_values=set_values if set_values else None,
        )

        if not rendered_docs:
            print_info("No templates to render")
            raise typer.Exit(0)

        # Validate rendered documents
        validate_rendered_docs(rendered_docs, result)

        # Show validation results if not quiet
        if not quiet:
            if result.failed:
                console.print("[bold red]Validation errors:[/bold red]")
                for check, error in result.failed:
                    console.print(f"  [red]✗[/red] {check}: {error}")
                console.print()

        # Output rendered templates
        if output_format == "json":
            import json
            for i, doc in enumerate(rendered_docs):
                if i > 0:
                    console.print()
                console.print(json.dumps(doc, indent=2))
        else:
            output_parts = []
            for doc in rendered_docs:
                output_parts.append(yaml.dump(doc, default_flow_style=False, sort_keys=False).rstrip())
            console.print("\n---\n".join(output_parts))

        # Exit with error if validation failed
        if result.failed:
            raise typer.Exit(1)

    except HelmError as e:
        print_error(f"Helm template rendering failed: {e}")
        raise typer.Exit(1)
