"""Templates CLI commands for NIKAME."""
from __future__ import annotations

import json
import shutil
from pathlib import Path
from typing import Any

import click
from rich.console import Console
from rich.panel import Panel
from rich.table import Table

from nikame.config.template import WizardSession, load_template
from nikame.utils.logger import console

USER_TEMPLATE_DIR = Path.home() / ".nikame" / "templates"
BUILTIN_TEMPLATE_DIR = Path(__file__).parent.parent.parent / "templates" / "builtin"

@click.group(name="templates")
def templates_group() -> None:
    """Manage local and built-in NIKAME project templates."""
    pass

def _get_all_templates() -> dict[str, dict[str, Any]]:
    """Returns a dict mapping template paths to their origin (builtin/user)."""
    templates: dict[str, dict[str, Any]] = {}
    
    if BUILTIN_TEMPLATE_DIR.exists():
        for t in BUILTIN_TEMPLATE_DIR.glob("*.nikame-template.json"):
            templates[t.name] = {"path": t, "type": "built-in"}
            
    if USER_TEMPLATE_DIR.exists():
        for t in USER_TEMPLATE_DIR.glob("*.nikame-template.json"):
            templates[t.name] = {"path": t, "type": "user"}
            
    return templates

@templates_group.command()
@click.argument("name")
def save(name: str) -> None:
    """Save the current project's configuration as a reusable template."""
    session_file = Path(".nikame/session.json")
    if not session_file.exists():
        console.print("[bold red]❌ No session found for this project. Re-run nikame init to generate one.[/bold red]")
        raise SystemExit(1)
        
    USER_TEMPLATE_DIR.mkdir(parents=True, exist_ok=True)
    
    dest_file = USER_TEMPLATE_DIR / f"{name}.nikame-template.json"
    shutil.copy(session_file, dest_file)
    console.print(f"[success]✨ Template '{name}' saved to {dest_file}[/success]")

@templates_group.command(name="list")
def list_cmd() -> None:
    """List available project templates."""
    templates = _get_all_templates()
    
    if not templates:
        console.print("[warning]No templates found. Generate one with 'nikame init' and then 'nikame templates save <name>'[/warning]")
        return
        
    table = Table(title="NIKAME Templates")
    table.add_column("Template ID", style="cyan", no_wrap=True)
    table.add_column("Type", style="magenta")
    table.add_column("Databases", style="green")
    table.add_column("MLOps", style="yellow", justify="center")
    table.add_column("Models", justify="right")
    
    for temp_file, info in sorted(templates.items()):
        name = temp_file.replace(".nikame-template.json", "")
        session = load_template(info["path"])
        if not session:
            continue
            
        dbs = ", ".join(session.databases) if session.databases else "none"
        mlops = "Yes ✓" if session.enable_mlops else "No"
        models_count = str(len(session.models))
        
        table.add_row(name, info["type"], dbs, mlops, models_count)
        
    console.print(table)

@templates_group.command()
@click.argument("name")
def inspect(name: str) -> None:
    """Inspect the data models of a specific template."""
    templates = _get_all_templates()
    filename = f"{name}.nikame-template.json"
    
    if filename not in templates:
        console.print(f"[bold red]❌ Template '{name}' not found.[/bold red]")
        return
        
    session = load_template(templates[filename]["path"])
    if not session:
        console.print(f"[bold red]❌ Template '{name}' is corrupt or cannot be loaded.[/bold red]")
        return
        
    console.print(Panel(f"[bold cyan]Template:[/bold cyan] {name} ({templates[filename]['type']})\n"
                        f"[bold cyan]Deployment Target:[/bold cyan] {session.target}\n"
                        f"[bold cyan]Scale:[/bold cyan] {session.scale}"))
                        
    if not session.models:
        console.print("[info]No data models defined in this template.[/info]")
        return
        
    for model_name, model_attrs in session.models.items():
        table = Table(title=f"Model: {model_name}", show_header=True, header_style="bold magenta")
        table.add_column("Field")
        table.add_column("Type")
        table.add_column("Required")
        table.add_column("Unique")
        
        # Handle dict or DataModelConfig instance
        fields_dict = model_attrs.get("fields", {}) if isinstance(model_attrs, dict) else getattr(model_attrs, "fields", {})
        
        for field_name, field_def in fields_dict.items():
            typ = field_def.get("type", "unknown") if isinstance(field_def, dict) else getattr(field_def, "type", "unknown")
            req = str(field_def.get("required", False) if isinstance(field_def, dict) else getattr(field_def, "required", False))
            uniq = str(field_def.get("unique", False) if isinstance(field_def, dict) else getattr(field_def, "unique", False))
            
            table.add_row(field_name, typ, req, uniq)
            
        console.print(table)
        console.print()
@templates_group.command()
@click.argument("query", default="")
@click.option("--user", default=None)
@click.option("--sort", default="stars")
@click.option("--desc", is_flag=True)
def search(query: str, user: str | None, sort: str, desc: bool) -> None:
    """Search for public NIKAME templates (Alias to list in v0.8.0)."""
    list_cmd.callback()

@templates_group.command()
@click.argument("name")
@click.pass_context
def use(ctx: click.Context, name: str) -> None:
    """Scaffold a new project from a template."""
    from nikame.cli.commands.init import init
    # Forward to nikame init --template <name>
    ctx.invoke(init, template=name)
