"""Step-by-step wizard for first-run onboarding.

Goal: avoid the multi-item "Settings" list menu on first launch, and instead
guide the user through only the minimum model/provider setup needed.
"""

from __future__ import annotations

from typing import Callable, Dict, Optional

from armorer.config import ConfigManager
from armorer.cli import common as cli_common
from armorer.cli.model_catalog import (
    CUSTOM_MODEL_CHOICE,
    DEFAULT_MODELS,
    get_latest_models,
)


_PROVIDER_CHOICES = ["openai", "anthropic", "gemini", "bedrock", "openrouter", "ollama"]

_PROVIDER_KEY_ENV: Dict[str, str] = {
    "openai": "OPENAI_API_KEY",
    "anthropic": "ANTHROPIC_API_KEY",
    "gemini": "GEMINI_API_KEY",
    "openrouter": "OPENROUTER_API_KEY",
    # bedrock is supported in config_cmd as BEDROCK_API_KEY
    "bedrock": "BEDROCK_API_KEY",
}


def _prompt_secret(key_name: str) -> Optional[str]:
    val = cli_common.questionary.password(f"Enter {key_name}:").ask()
    if val is None:
        return None
    val = str(val).strip()
    return val or None


def _print_telegram_botfather_help() -> None:
    cli_common.console.print(
        "[bold]Telegram bot setup (BotFather)[/bold]\n"
        "1) Open Telegram and message [bold]@BotFather[/bold]\n"
        "2) Send [bold]/newbot[/bold]\n"
        "3) Choose a bot name and username (must end with [bold]bot[/bold])\n"
        "4) Copy the token BotFather returns and paste it below"
    )


def _maybe_configure_telegram(step_label: str, cm: ConfigManager) -> None:
    enable_telegram = cli_common.questionary.confirm(
        f"{step_label}: Enable Telegram now?",
        default=False,
    ).ask()
    if not enable_telegram:
        cli_common.console.print(
            "[dim]Skipping Telegram setup. You can run `armorer app configure openclaw` later.[/dim]"
        )
        return

    existing = str(cm.find_vault_key("TELEGRAM_BOT_TOKEN") or "").strip()
    if existing:
        keep_existing = cli_common.questionary.confirm(
            "Telegram bot token is already configured. Keep it?",
            default=True,
        ).ask()
        if keep_existing:
            cli_common.console.print("[green]✓ Keeping existing Telegram bot token.[/green]")
            return

    needs_help = cli_common.questionary.confirm(
        "Need help creating a Telegram bot with BotFather first?",
        default=True,
    ).ask()
    if needs_help:
        _print_telegram_botfather_help()

    token = _prompt_secret("TELEGRAM_BOT_TOKEN")
    if not token:
        cli_common.console.print(
            "[yellow]No Telegram bot token provided; Telegram setup skipped.[/yellow]"
        )
        return

    cm.save_to_vault(
        "TELEGRAM_BOT_TOKEN",
        token,
        description="Armorer Telegram Bot Token",
        aliases=["ARMORER_TELEGRAM_BOT_TOKEN"],
    )
    cli_common.console.print("[green]✓ Stored TELEGRAM_BOT_TOKEN in vault.[/green]")


def run_initial_setup_wizard(*, print_logo: Callable[[], None], model_provider_only: bool = False) -> None:
    """Interactive wizard that sets MODEL_PROVIDER and Armorer_MODEL.

    Minimum required completion:
    - MODEL_PROVIDER is set
    """
    print_logo()
    cm = ConfigManager()

    provider = cli_common.questionary.select(
        "Step 1/3: Choose your model provider",
        choices=_PROVIDER_CHOICES,
        default="openai" if "openai" in _PROVIDER_CHOICES else _PROVIDER_CHOICES[0],
    ).ask()
    if not provider:
        raise KeyboardInterrupt()

    provider = str(provider).strip().lower()
    if provider not in DEFAULT_MODELS:
        raise KeyboardInterrupt()

    cm.set_key("MODEL_PROVIDER", provider)

    default_model = DEFAULT_MODELS.get(provider) or ""
    model_choices = get_latest_models(provider, cm)
    model_selection = cli_common.questionary.select(
        "Step 2/3: Choose a model (or enter custom)",
        choices=model_choices + [CUSTOM_MODEL_CHOICE],
        default=default_model if default_model in model_choices else None,
    ).ask()
    if not model_selection:
        raise KeyboardInterrupt()

    if model_selection == CUSTOM_MODEL_CHOICE:
        model = cli_common.questionary.text(
            f"Enter custom Model ID (default: {default_model})",
            default=default_model,
        ).ask()
        model = str(model or default_model).strip()
    else:
        model = str(model_selection).strip()
    cm.set_key("Armorer_MODEL", model)

    if model_provider_only:
        cli_common.console.print("[green]✓ Provider + model saved.[/green]")
        return

    # Step 3/4: provider credential hints (optional on first run; users can fill later)
    if provider == "ollama":
        base_url = cli_common.questionary.text(
            "Optional: Ollama Base URL (default: http://localhost:11434/v1/)",
            default="http://localhost:11434/v1/",
        ).ask()
        if base_url:
            cm.set_key("OLLAMA_BASE_URL", str(base_url).strip())
        cli_common.console.print("[green]✓ Ollama settings saved.[/green]")
    else:
        key_env = _PROVIDER_KEY_ENV.get(provider)
        if not key_env:
            cli_common.console.print("[yellow]No API key mapping for this provider; skipping.[/yellow]")
        else:
            set_key = cli_common.questionary.confirm(
                f"Step 3/4: Do you want to store {key_env} now?",
                default=False,
            ).ask()
            if set_key:
                key_val = _prompt_secret(key_env)
                if not key_val:
                    cli_common.console.print(
                        "[yellow]No value provided; skipping API key storage.[/yellow]"
                    )
                else:
                    cm.save_to_vault(key_env, key_val, description=f"{provider.capitalize()} API Key")
                    cli_common.console.print(f"[green]✓ Stored {key_env} in vault.[/green]")
            else:
                cli_common.console.print(
                    "[dim]Skipping API key entry. You can run `armorer config` later to add it.[/dim]"
                )

    _maybe_configure_telegram("Step 4/4", cm)

