"""Onboarding flow — interactive first-time configuration wizard.

When no agentkit.yaml exists, this wizard guides the user through:
1. Choosing an LLM provider
2. Entering API key
3. Selecting a default model
4. Generating agentkit.yaml + .env
"""

from __future__ import annotations

import os
from pathlib import Path
from typing import Any

import yaml
from rich.panel import Panel
from rich.prompt import Prompt, Confirm
from rich import print as rprint

from agentkit.server.config import find_config_path


# ── Provider presets ──────────────────────────────────────────────────

PROVIDER_PRESETS: dict[str, dict[str, Any]] = {
    "deepseek": {
        "name": "DeepSeek",
        "env_key": "DEEPSEEK_API_KEY",
        "base_url": "https://api.deepseek.com/v1",
        "type": "openai",
        "models": {
            "deepseek-chat": {"alias": "default"},
            "deepseek-reasoner": {"alias": "reasoning"},
        },
        "default_model": "deepseek-chat",
    },
    "openai": {
        "name": "OpenAI",
        "env_key": "OPENAI_API_KEY",
        "base_url": "https://api.openai.com/v1",
        "type": "openai",
        "models": {
            "gpt-4o": {"alias": "default"},
            "gpt-4o-mini": {"alias": "fast"},
        },
        "default_model": "gpt-4o",
    },
    "bailian-coding": {
        "name": "百炼 Coding Plan",
        "env_key": "DASHSCOPE_API_KEY",
        "base_url": "https://coding.dashscope.aliyuncs.com/v1",
        "type": "openai",
        "models": {
            "qwen3.7-plus": {"alias": "default"},
            "qwen3.6-plus": {},
            "qwen3.5-plus": {},
            "qwen3-max-2026-01-23": {},
            "qwen3-coder-plus": {"alias": "coder"},
            "qwen3-coder-next": {},
            "kimi-k2.5": {},
            "glm-5": {},
            "glm-4.7": {},
            "MiniMax-M2.5": {},
        },
        "default_model": "qwen3.7-plus",
    },
    "qwen": {
        "name": "通义千问 (Qwen/DashScope)",
        "env_key": "DASHSCOPE_API_KEY",
        "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
        "type": "openai",
        "models": {
            "qwen-plus": {"alias": "default"},
            "qwen-turbo": {"alias": "fast"},
        },
        "default_model": "qwen-plus",
    },
    "doubao": {
        "name": "豆包 (Doubao)",
        "env_key": "DOUBAO_API_KEY",
        "base_url": "https://ark.cn-beijing.volces.com/api/v3",
        "type": "openai",
        "models": {
            "doubao-pro-32k": {"alias": "default"},
        },
        "default_model": "doubao-pro-32k",
    },
    "gemini": {
        "name": "Google Gemini",
        "env_key": "GEMINI_API_KEY",
        "base_url": "https://generativelanguage.googleapis.com",
        "type": "gemini",
        "models": {
            "gemini-2.0-flash": {"alias": "default"},
        },
        "default_model": "gemini-2.0-flash",
    },
    "anthropic": {
        "name": "Anthropic Claude",
        "env_key": "ANTHROPIC_API_KEY",
        "base_url": "https://api.anthropic.com",
        "type": "anthropic",
        "models": {
            "claude-sonnet-4-20250514": {"alias": "default"},
        },
        "default_model": "claude-sonnet-4-20250514",
    },
}


def needs_onboarding(config_arg: str | None = None) -> bool:
    """Check if onboarding is needed (no config file found)."""
    return find_config_path(config_arg) is None


def run_onboarding(
    output_dir: str = ".",
    config_arg: str | None = None,
) -> str | None:
    """Run the interactive onboarding wizard.

    Returns:
        Path to the generated config file, or None if cancelled.
    """
    rprint(Panel(
        "[bold]Welcome to AgentKit![/bold]\n\n"
        "No configuration file found. Let's set up your first Agent.\n"
        "This will create [cyan]agentkit.yaml[/cyan] and [cyan].env[/cyan] for you.",
        title="AgentKit Setup",
        border_style="bright_blue",
    ))

    output_path = Path(output_dir).resolve()
    output_path.mkdir(parents=True, exist_ok=True)

    # ── Step 1: Choose LLM provider ──────────────────────────────
    rprint("\n[bold]Step 1: Choose your LLM provider[/bold]")
    provider_keys = list(PROVIDER_PRESETS.keys())
    for i, key in enumerate(provider_keys, 1):
        preset = PROVIDER_PRESETS[key]
        rprint(f"  [cyan]{i}[/cyan]. {preset['name']}")

    choice = Prompt.ask(
        "\nSelect a provider",
        choices=[str(i) for i in range(1, len(provider_keys) + 1)],
        default="1",
    )
    selected_key = provider_keys[int(choice) - 1]
    preset = PROVIDER_PRESETS[selected_key]

    rprint(f"\n[green]Selected: {preset['name']}[/green]")

    # ── Step 2: Enter API key ─────────────────────────────────────
    rprint(f"\n[bold]Step 2: Enter your API key[/bold]")
    rprint(f"You can get one from the {preset['name']} dashboard.")
    api_key = Prompt.ask(
        f"  {preset['env_key']}",
        password=True,
    )

    if not api_key.strip():
        rprint("[red]API key is required. Onboarding cancelled.[/red]")
        return None

    # ── Step 2b: Select default model ────────────────────────────
    available_models = list(preset["models"].keys())
    if len(available_models) > 1:
        rprint(f"\n[bold]Step 2b: Select your default model[/bold]")
        for i, model in enumerate(available_models, 1):
            alias = preset["models"][model].get("alias", "")
            alias_str = f" [dim]({alias})[/dim]" if alias else ""
            recommended = " [green]← recommended[/green]" if model == preset.get("default_model") else ""
            rprint(f"  [cyan]{i}[/cyan]. {model}{alias_str}{recommended}")
        model_choice = Prompt.ask(
            "Select default model",
            choices=[str(i) for i in range(1, len(available_models) + 1)],
            default=str(available_models.index(preset.get("default_model", available_models[0])) + 1),
        )
        selected_model = available_models[int(model_choice) - 1]
        # Rebuild models dict: selected model gets "default" alias
        updated_models: dict[str, Any] = {}
        for model, conf in preset["models"].items():
            if model == selected_model:
                updated_models[model] = {**conf, "alias": "default"}
            else:
                # Remove "default" alias from other models
                updated_models[model] = {k: v for k, v in conf.items() if k != "alias" or v != "default"}
        preset = {**preset, "models": updated_models}
        rprint(f"[green]Selected: {selected_model}[/green]")
    else:
        selected_model = available_models[0]

    # ── Step 3: Optional — add a second provider ─────────────────
    env_vars: dict[str, str] = {preset["env_key"]: api_key.strip()}
    providers_config: dict[str, Any] = {
        selected_key: {
            "api_key": f"${{{preset['env_key']}}}",
            "base_url": preset["base_url"],
            "type": preset["type"],
            "models": preset["models"],
        }
    }
    model_aliases: dict[str, str] = {alias: f"{selected_key}/{model}" for model, conf in preset["models"].items() if (alias := conf.get("alias"))}

    if Confirm.ask("\nWould you like to add a second LLM provider (for fallback)?", default=False):
        remaining = [k for k in provider_keys if k != selected_key]
        for i, key in enumerate(remaining, 1):
            rprint(f"  [cyan]{i}[/cyan]. {PROVIDER_PRESETS[key]['name']}")
        choice2 = Prompt.ask(
            "Select second provider (or press Enter to skip)",
            choices=[str(i) for i in range(1, len(remaining) + 1)] + [""],
            default="",
        )
        if choice2:
            key2 = remaining[int(choice2) - 1]
            preset2 = PROVIDER_PRESETS[key2]
            api_key2 = Prompt.ask(f"  {preset2['env_key']}", password=True)
            if api_key2.strip():
                env_vars[preset2["env_key"]] = api_key2.strip()
                providers_config[key2] = {
                    "api_key": f"${{{preset2['env_key']}}}",
                    "base_url": preset2["base_url"],
                    "type": preset2["type"],
                    "models": preset2["models"],
                }
                for model, conf in preset2["models"].items():
                    alias = conf.get("alias")
                    if alias and alias not in model_aliases:
                        model_aliases[alias] = f"{key2}/{model}"

    # ── Step 4: Generate config files ─────────────────────────────
    rprint("\n[bold]Step 3: Generating configuration...[/bold]")

    config = {
        "server": {
            "host": "0.0.0.0",
            "port": 8001,
            "workers": 1,
            "rate_limit": 60,
        },
        "llm": {
            "providers": providers_config,
            "model_aliases": model_aliases,
        },
        "session": {
            "backend": "memory",
        },
        "bus": {
            "backend": "memory",
        },
        "task_store": {
            "backend": "memory",
        },
        "skills": {
            "auto_discover": True,
            "paths": ["./skills"],
        },
        "logging": {
            "level": "INFO",
            "format": "text",
        },
    }

    # Write agentkit.yaml
    config_path = output_path / "agentkit.yaml"
    with open(config_path, "w", encoding="utf-8") as f:
        yaml.dump(config, f, default_flow_style=False, allow_unicode=True, sort_keys=False)
    rprint(f"  [green]Created:[/green] {config_path}")

    # Write .env
    env_path = output_path / ".env"
    env_lines = [f"{k}={v}" for k, v in env_vars.items()]
    with open(env_path, "w", encoding="utf-8") as f:
        f.write("# AgentKit Environment Variables\n")
        f.write("# Generated by onboarding wizard\n\n")
        f.write("\n".join(env_lines) + "\n")
    rprint(f"  [green]Created:[/green] {env_path}")

    # ── Step 4: Agent personality (optional) ──────────────────────
    rprint("\n[bold]Step 4: Customize your Agent (optional)[/bold]")
    rprint("  Press Enter to use defaults, or type your preferences.")

    agent_name = Prompt.ask("  Agent name", default="AgentKit")
    personality = Prompt.ask("  Personality", default="专业、友好、注重细节")
    speaking_style = Prompt.ask("  Speaking style", default="简洁清晰")

    # Create SOUL.md
    from agentkit.memory.profile import MemoryStore
    memory_store = MemoryStore(base_dir=Path.home() / ".agentkit")
    soul_content = f"""## 身份
我是{agent_name}，一个专业的 AI 助手。

## 性格
{personality}

## 说话方式
{speaking_style}

## 做事准则
- 准确回答用户问题
- 主动记住用户提到的偏好和信息
- 不确定时坦诚说明
"""
    memory_store.get_file("soul").write(soul_content.strip())
    rprint(f"  [green]Created:[/green] ~/.agentkit/SOUL.md")

    rprint(Panel(
        "[bold green]Setup complete![/bold green]\n\n"
        "You can now run:\n"
        "  [cyan]agentkit chat[/cyan]  — Start chatting with your Agent\n"
        "  [cyan]agentkit serve[/cyan] — Start the API server",
        border_style="green",
    ))

    return str(config_path)
