"""
FORGE Onboarding Wizard
=======================
Beautiful interactive first-run setup using questionary.
Guides users through API keys, models, Telegram setup.
"""
from __future__ import annotations

import asyncio
import sys
from pathlib import Path
from typing import Optional

from rich.console import Console
from rich.panel import Panel
from rich.text import Text

console = Console()

try:
    import questionary
    from questionary import Style as QStyle

    FORGE_STYLE = QStyle([
        ("qmark", "fg:#f0a500 bold"),
        ("question", "bold"),
        ("answer", "fg:#00d4aa bold"),
        ("pointer", "fg:#f0a500 bold"),
        ("highlighted", "fg:#f0a500 bold"),
        ("selected", "fg:#00d4aa"),
        ("separator", "fg:#444444"),
        ("instruction", "fg:#888888"),
        ("text", ""),
        ("disabled", "fg:#888888 italic"),
    ])
    QUESTIONARY_AVAILABLE = True
except ImportError:
    QUESTIONARY_AVAILABLE = False


def _qmark(prompt: str, **kwargs):
    """Wrapper that always applies FORGE style."""
    if QUESTIONARY_AVAILABLE:
        return questionary.text(prompt, style=FORGE_STYLE, **kwargs)
    else:
        # Fallback to input()
        class _FallbackPrompt:
            def ask(self_inner):
                val = input(f"  {prompt}: ").strip()
                return val or kwargs.get("default", "")
        return _FallbackPrompt()


def _select(prompt: str, choices: list, **kwargs):
    if QUESTIONARY_AVAILABLE:
        return questionary.select(prompt, choices=choices, style=FORGE_STYLE, **kwargs)
    else:
        class _FallbackSelect:
            def ask(self_inner):
                for i, c in enumerate(choices):
                    console.print(f"  [{i}] {c}")
                idx = input(f"  {prompt} [0]: ").strip()
                try:
                    return choices[int(idx)]
                except Exception:
                    return choices[0]
        return _FallbackSelect()


def _confirm(prompt: str, default: bool = True):
    if QUESTIONARY_AVAILABLE:
        return questionary.confirm(prompt, default=default, style=FORGE_STYLE)
    else:
        class _FallbackConfirm:
            def ask(self_inner):
                ans = input(f"  {prompt} ({'Y/n' if default else 'y/N'}): ").strip().lower()
                if not ans:
                    return default
                return ans.startswith("y")
        return _FallbackConfirm()


def _password(prompt: str):
    if QUESTIONARY_AVAILABLE:
        return questionary.password(prompt, style=FORGE_STYLE)
    else:
        import getpass
        class _FallbackPassword:
            def ask(self_inner):
                return getpass.getpass(f"  {prompt}: ").strip()
        return _FallbackPassword()


# ─────────────────────────────────────────────────────────────────────────────

def run_onboarding(settings_cls) -> "Settings":
    """
    Run the full interactive onboarding wizard.
    Returns a populated Settings object (not yet saved).
    """
    from forge.settings import Settings

    console.print()
    console.print(Panel(
        Text.from_markup(
            "  Welcome to [bold yellow]FORGE AI[/bold yellow]!\n\n"
            "  Let's get you set up in under 2 minutes.\n"
            "  API keys are stored securely in [dim]~/.forge/config.json[/dim] (chmod 600).\n\n"
            "  [dim]Press Ctrl+C at any time to skip remaining steps.[/dim]"
        ),
        title="[bold yellow]🔨 First-time Setup[/bold yellow]",
        border_style="yellow",
    ))

    existing = Settings.load()
    updated: dict = {}

    try:
        # ── Step 1: Groq API Key ──────────────────────────────────────────
        console.print("\n  [bold]Step 1/4: Groq API Key[/bold]")
        console.print("  [dim]Get yours FREE at https://console.groq.com[/dim]")
        console.print("  [dim]Groq provides ultra-fast LLaMA 3.3 70B inference.[/dim]\n")

        groq_key = _password("  Groq API Key (gsk_...)").ask()
        if groq_key:
            updated["groq_api_key"] = groq_key
            console.print("  [green]✓ Groq key saved[/green]")
        else:
            console.print("  [yellow]⚠ Skipped — set GROQ_API_KEY env var later[/yellow]")

        # ── Step 2: NVIDIA NIM Key ────────────────────────────────────────
        console.print("\n  [bold]Step 2/4: NVIDIA NIM API Key[/bold]")
        console.print("  [dim]Get yours at https://build.nvidia.com (free credits available)[/dim]")
        console.print("  [dim]NVIDIA NIM runs CodeLlama 70B for superior code generation.[/dim]\n")

        nvidia_key = _password("  NVIDIA NIM API Key (nvapi-...)").ask()
        if nvidia_key:
            updated["nvidia_api_key"] = nvidia_key
            console.print("  [green]✓ NVIDIA key saved[/green]")
        else:
            console.print("  [yellow]⚠ Skipped — set NVIDIA_API_KEY env var later[/yellow]")

        # ── Step 3: Telegram (optional) ───────────────────────────────────
        console.print("\n  [bold]Step 3/4: Telegram Bot (optional)[/bold]")
        console.print("  [dim]Connect a Telegram bot to generate apps from your phone.[/dim]")
        console.print("  [dim]Create a bot via @BotFather on Telegram.[/dim]\n")

        wants_telegram = _confirm("  Set up Telegram bot?", default=False).ask()

        if wants_telegram:
            console.print(
                "\n  [dim]How to create a bot:[/dim]\n"
                "  1. Open Telegram, search [bold]@BotFather[/bold]\n"
                "  2. Send [bold]/newbot[/bold] and follow instructions\n"
                "  3. Copy the token (format: 123456:ABC-DEF...)\n"
                "  4. Get your chat ID: search [bold]@userinfobot[/bold] and send /start\n"
            )
            tg_token = _password("  Bot Token (from @BotFather)").ask()
            tg_chat_id = _qmark("  Your Chat ID (from @userinfobot)").ask()

            if tg_token:
                updated["telegram_bot_token"] = tg_token
            if tg_chat_id:
                updated["telegram_chat_id"] = tg_chat_id

            if tg_token and tg_chat_id:
                console.print("  [green]✓ Telegram configured[/green]")
            else:
                console.print("  [yellow]⚠ Telegram skipped (incomplete)[/yellow]")

        # ── Step 4: Preferences ───────────────────────────────────────────
        console.print("\n  [bold]Step 4/4: Generation Preferences[/bold]\n")

        complexity = _select(
            "  Default complexity",
            choices=[
                "minimal  (4 screens — quick prototype)",
                "standard (7 screens — solid app)  ← recommended",
                "full     (12 screens — feature-rich)",
                "enterprise (18 screens — full product)",
            ],
            default="standard (7 screens — solid app)  ← recommended",
        ).ask()
        complexity_map = {"minimal": "minimal", "standard": "standard", "full": "full", "enterprise": "enterprise"}
        for k, v in complexity_map.items():
            if complexity and complexity.startswith(k):
                updated["complexity"] = v
                break

        output_dir = _qmark("  Default output directory", default=".").ask()
        if output_dir:
            updated["output_dir"] = output_dir

        # Apply updates
        import os, json
        from forge.settings import CONFIG_DIR, CONFIG_FILE

        file_data: dict = {}
        if CONFIG_FILE.exists():
            try:
                file_data = json.loads(CONFIG_FILE.read_text())
            except Exception:
                pass

        file_data.update(updated)
        CONFIG_DIR.mkdir(parents=True, exist_ok=True)
        CONFIG_FILE.write_text(json.dumps(file_data, indent=2))
        CONFIG_FILE.chmod(0o600)

        console.print(
            Panel(
                Text.from_markup(
                    "  [bold green]✓ Setup complete![/bold green]\n\n"
                    f"  Config saved to [dim]{CONFIG_FILE}[/dim]\n\n"
                    "  [bold]Try it:[/bold]\n"
                    "  [cyan]forge generate \"A habit tracker with streaks\"[/cyan]\n\n"
                    "  [dim]Run[/dim] [cyan]forge doctor[/cyan] [dim]to verify API connections.[/dim]"
                ),
                border_style="green",
                title="[bold green]🎉 Ready![/bold green]",
            )
        )

        # Reload with new values
        return Settings.load()

    except KeyboardInterrupt:
        console.print("\n\n  [yellow]Setup interrupted. Run [cyan]forge config[/cyan] to complete.[/yellow]\n")
        return Settings.load()
