"""
llmpm list             — show all installed models
llmpm info <model>     — show detailed info about a single model
llmpm uninstall <model> — uninstall a model
"""

# pylint: disable=duplicate-code
from __future__ import annotations

import shutil
from pathlib import Path

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

from llmpm import display
from llmpm.commands._picker import pick_installed_model
from llmpm.core import llmpm_json, registry
from llmpm.display import fmt_size

_info_console = Console()


# ── list ──────────────────────────────────────────────────────────────────────

@click.command("list")
def list_models() -> None:
    """List all installed models."""
    display.header("installed models")
    display.blank()
    models = registry.all_models()
    display.models_table(models)


# ── info ──────────────────────────────────────────────────────────────────────

@click.command("info")
@click.argument("repo_id")
def info(repo_id: str) -> None:
    """Show detailed information about an installed model."""
    display.header(f"info {repo_id}")
    display.blank()

    matches = registry.find_models(repo_id)
    if not matches:
        display.error(
            f"Model [bold]{repo_id}[/] is not installed.\n\n"
            f"  Run:  [bold cyan]llmpm install {repo_id}[/]"
        )
        raise SystemExit(1)

    if len(matches) == 1:
        matched_id, entry = matches[0]
        if matched_id != repo_id:
            display.info(f"Using [bold]{matched_id}[/]")
    else:
        result = pick_installed_model(matches, repo_id)
        if result is None:
            raise SystemExit(0)
        matched_id, entry = result

    repo_id = matched_id

    table = Table.grid(padding=(0, 2))
    table.add_column(style="dim", justify="right")
    table.add_column()

    badge = display.model_type_badge(entry.get("model_type", "?"))
    backend = (
        "llama.cpp"
        if entry["model_type"] == "gguf"
        else "HuggingFace Transformers"
    )

    table.add_row("model", f"[bold]{entry['repo_id']}[/]")
    table.add_row("type", badge)
    table.add_row("backend", backend)
    table.add_row("path", f"[dim]{entry['path']}[/]")

    if entry.get("primary_file"):
        table.add_row("primary file", f"[dim]{entry['primary_file']}[/]")

    if entry.get("files"):
        files_str = (
            "\n".join(f"[dim]  {fname}[/]" for fname in entry["files"])
            or "—"
        )
        table.add_row("files", files_str)

    if entry.get("size_bytes"):
        table.add_row("size", fmt_size(entry["size_bytes"]))

    if entry.get("installed_at"):
        table.add_row(
            "installed",
            entry["installed_at"][:19].replace("T", " "),
        )

    if entry.get("tags"):
        tags_str = "  ".join(
            f"[dim]{tag}[/]" for tag in entry["tags"][:8]
        )
        table.add_row("tags", tags_str)

    _info_console.print(Panel(table, border_style="dim", padding=(0, 2)))
    _info_console.print()


# ── uninstall ─────────────────────────────────────────────────────────────────

@click.command("uninstall")
@click.argument("repo_id")
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation prompt.")
def uninstall(repo_id: str, yes: bool) -> None:
    """Uninstall a model."""
    display.header(f"uninstall {repo_id}")
    display.blank()

    matches = registry.find_models(repo_id)
    if not matches:
        display.error(f"Model [bold]{repo_id}[/] is not installed.")
        raise SystemExit(1)

    if len(matches) == 1:
        matched_id, entry = matches[0]
        if matched_id != repo_id:
            display.info(f"Using [bold]{matched_id}[/]")
    else:
        result = pick_installed_model(matches, repo_id)
        if result is None:
            raise SystemExit(0)
        matched_id, entry = result

    repo_id = matched_id

    size_str = fmt_size(entry.get("size_bytes") or 0)
    display.warn(
        f"This will delete [bold]{repo_id}[/] "
        f"({size_str}) from disk."
    )
    display.blank()

    if not yes:
        confirmed = click.confirm("  Continue?", default=False)
        if not confirmed:
            display.info("Cancelled.")
            raise SystemExit(0)

    model_path = Path(entry["path"])
    if model_path.exists():
        shutil.rmtree(model_path, ignore_errors=True)
        display.ok(f"Deleted {model_path}")

    registry.unregister(repo_id)
    display.ok(f"Removed [bold]{repo_id}[/] from registry")

    if llmpm_json.remove_dependency(repo_id):
        display.ok(f"Removed [bold]{repo_id}[/] from [bold]llmpm.json[/] dependencies")

    display.blank()
