"""rc init — set up node identity and register with the network."""

from __future__ import annotations

import typer
from rich.console import Console
from rich.panel import Panel

from rc.auth import generate_node_secret, hash_node_secret
from rc.config import (
    CONFIG_PATH,
    NodeConfig,
    generate_node_id,
    get_default_backend_url,
    save_config,
)
from rc.inference.catalog import get_default_model_repo
from rc.inference.provision import (
    auto_select_model,
    download_model,
    provisioning_summary,
)

console = Console()


def run(
    name: str = typer.Option("default-node", "--name", "-n", help="Node display name"),
    role: str = typer.Option(
        "both",
        "--role",
        "-r",
        help="Node role: provider, requester, or both",
    ),
    supabase_url: str = typer.Option(..., "--supabase-url", envvar="SUPABASE_URL", help="Supabase project URL"),
    supabase_key: str = typer.Option(..., "--supabase-key", envvar="SUPABASE_KEY", help="Supabase anon/service key"),
    backend_url: str | None = typer.Option(
        None,
        "--backend-url",
        envvar="RC_BACKEND_URL",
        help="Backend base URL for research job orchestration",
    ),
    model: str | None = typer.Option(
        None,
        "--model",
        "-m",
        help="Override the auto-selected model for inference",
    ),
    skip_model_download: bool = typer.Option(
        False,
        "--skip-model-download",
        help="Skip the initial model download during setup",
    ),
) -> None:
    """Initialize this node and register with the Research Capacitor network."""
    if role not in ("provider", "requester", "both"):
        console.print(f"[red]Invalid role '{role}'. Use provider, requester, or both.[/red]")
        raise typer.Exit(code=1)

    node_id = generate_node_id()
    node_secret = generate_node_secret()
    selected_model = model or ""
    model_path = ""
    model_downloaded = False
    accelerator = "unknown"
    gpu_count = 0
    gpu_vram_gb = None
    total_memory_gb = None
    gpu_name = None

    if role in ("provider", "both"):
        profile, recommended_model = auto_select_model()
        accelerator = profile.accelerator
        gpu_count = profile.gpu_count
        gpu_vram_gb = profile.total_vram_gb
        total_memory_gb = profile.total_memory_gb
        gpu_name = profile.gpu_name
        selected_model = model or recommended_model.repo_id

        summary_text = provisioning_summary(profile, recommended_model)
        if model and model != recommended_model.repo_id:
            summary_text += f"\nOverride:    {model}"
        console.print(
            Panel(summary_text, title="[bold]Provisioning[/bold]", border_style="cyan")
        )

        if not skip_model_download:
            with console.status(
                f"Downloading model [bold]{selected_model}[/bold]...", spinner="dots"
            ):
                try:
                    model_path = str(download_model(selected_model))
                    model_downloaded = True
                except Exception as exc:
                    console.print(f"[red]Model download failed: {exc}[/red]")
                    raise typer.Exit(code=1)
        else:
            console.print("[yellow]Skipping model download during setup.[/yellow]")
    else:
        selected_model = model or get_default_model_repo()

    config = NodeConfig(
        node_id=node_id,
        node_name=name,
        role=role,
        node_secret=node_secret,
        supabase_url=supabase_url,
        supabase_key=supabase_key,
        backend_url=(backend_url or get_default_backend_url()).rstrip("/"),
        model=selected_model,
        model_path=model_path,
        model_downloaded=model_downloaded,
        accelerator=accelerator,
        gpu_count=gpu_count,
        gpu_vram_gb=gpu_vram_gb,
        total_memory_gb=total_memory_gb,
        gpu_name=gpu_name,
    )

    save_config(config)
    console.print(f"[dim]Config written to {CONFIG_PATH}[/dim]")

    try:
        from rc.supabase_client import get_client

        client = get_client()
        client.rpc(
            "register_node",
            {
                "p_id": node_id,
                "p_name": name,
                "p_role": role,
                "p_public_key": "",
                "p_auth_token_hash": hash_node_secret(node_secret),
                "p_gpu_info": config.gpu_info_payload(),
            },
        ).execute()
    except Exception as exc:
        console.print(f"[red]Failed to register with Supabase: {exc}[/red]")
        console.print(
            "[yellow]Config was saved locally. You can retry registration later.[/yellow]"
        )
        raise typer.Exit(code=1)

    console.print(
        Panel(
            f"[bold]ID:[/bold]   {node_id}\n"
            f"[bold]Name:[/bold] {name}\n"
            f"[bold]Role:[/bold] {role}\n"
            f"[bold]Backend:[/bold] {config.backend_url}\n"
            f"[bold]Model:[/bold] {selected_model}\n"
            f"[bold]Download:[/bold] {'ready' if model_downloaded else 'pending'}",
            title="[green]Node Registered[/green]",
            border_style="green",
        )
    )
