"""AgentScout CLI entry point."""

from __future__ import annotations

import asyncio
from pathlib import Path

import typer
from agent_scout import __version__ as core_version
from agent_scout.config.settings import (
    DEFAULT_CONFIG_FILE,
    CustomEndpointSettings,
    Settings,
    load_settings,
    save_settings,
)
from rich.console import Console
from rich.panel import Panel
from rich.prompt import Confirm, Prompt
from rich.table import Table

from . import __version__ as cli_version

app = typer.Typer(
    name="agent-scout",
    help="AgentScout — Your personal AI assistant agent that scouts the web for you.",
    no_args_is_help=True,
)
console = Console()


def _load_settings() -> Settings:
    """Load settings with error display."""
    return load_settings()


# ---- run ----


@app.command()
def run(
    task: str = typer.Argument(
        help="Natural language description of what you want the agent to do",
    ),
    model: str | None = typer.Option(
        None, "--model", "-m", help="LLM model to use (overrides routing)"
    ),
    budget: float | None = typer.Option(
        None, "--budget", "-b", help="Max budget for this task (USD)"
    ),
    autonomy: str = typer.Option(None, "--autonomy", "-a", help="Autonomy level: full, semi, step"),
    verbose: bool = typer.Option(
        False, "--verbose", "-v", help="Show full observations and debug info"
    ),
):
    """Run a scouting task."""
    settings = _load_settings()

    if autonomy:
        settings.autonomy = autonomy
    if verbose:
        settings.verbose = True

    console.print(
        Panel(
            f"[bold]Task:[/bold] {task}",
            title="[bold green]AgentScout[/bold green]",
            subtitle="Starting...",
            border_style="green",
        )
    )

    from agent_scout_cli.commands.runner import run_task

    asyncio.run(
        run_task(
            task_description=task,
            settings=settings,
            console=console,
            model_override=model,
            budget_override=budget,
            verbose=verbose,
        )
    )


# ---- setup ----


@app.command()
def setup(
    reconfigure: bool = typer.Option(False, "--reconfigure", help="Reconfigure existing settings"),
):
    """Run the interactive setup wizard."""
    settings = _load_settings() if reconfigure else Settings()

    console.print(
        Panel(
            "[bold]Welcome to AgentScout![/bold]\n\n"
            "This wizard will help you configure your AI assistant.\n"
            "You can re-run this anytime with: [cyan]agent-scout setup --reconfigure[/cyan]",
            title="[bold green]Setup Wizard[/bold green]",
            border_style="green",
        )
    )

    # Step 1: LLM model
    console.print("\n[bold]Step 1: LLM Configuration[/bold]")
    settings.llm.default_model = Prompt.ask(
        "Default model",
        default=settings.llm.default_model,
    )

    # Step 2: API keys (optional)
    console.print("\n[bold]Step 2: Search API Keys[/bold] [dim](optional, Enter to skip)[/dim]")
    settings.search.tavily_api_key = Prompt.ask(
        "Tavily API key", default=settings.search.tavily_api_key or "", show_default=False
    )
    settings.search.serpapi_api_key = Prompt.ask(
        "SerpAPI key", default=settings.search.serpapi_api_key or "", show_default=False
    )
    settings.search.brave_api_key = Prompt.ask(
        "Brave Search key", default=settings.search.brave_api_key or "", show_default=False
    )

    # Step 3: Custom endpoints
    console.print("\n[bold]Step 3: Custom LLM Endpoints[/bold]")
    while Confirm.ask("Add a custom LLM endpoint?", default=False):
        ep = CustomEndpointSettings(
            name=Prompt.ask("Endpoint name (e.g., 'myapi')"),
            base_url=Prompt.ask("Base URL"),
            api_key=Prompt.ask("API key"),
            model_name=Prompt.ask("Model name"),
        )
        settings.custom_endpoints.append(ep)

    # Step 4: Budget
    console.print("\n[bold]Step 4: Budget Limits[/bold]")
    settings.budget.task_limit = float(
        Prompt.ask("Max per-task spend (USD)", default=str(settings.budget.task_limit))
    )
    settings.budget.daily_limit = float(
        Prompt.ask("Max daily spend (USD)", default=str(settings.budget.daily_limit))
    )
    settings.budget.monthly_limit = float(
        Prompt.ask("Max monthly spend (USD)", default=str(settings.budget.monthly_limit))
    )

    # Step 5: Personality
    console.print("\n[bold]Step 5: Personality[/bold]")
    settings.personality = Prompt.ask(
        "Agent personality",
        choices=["helpful", "concise", "detailed", "casual"],
        default=settings.personality,
    )

    # Save
    save_settings(settings)
    console.print(
        Panel(
            f"Configuration saved to [cyan]{DEFAULT_CONFIG_FILE}[/cyan]\n\n"
            "You're all set! Run a task with:\n"
            '[bold]agent-scout run "Find me the best deal on..."[/bold]',
            title="[bold green]Setup Complete[/bold green]",
            border_style="green",
        )
    )


# ---- config ----


@app.command()
def config(
    action: str = typer.Argument("show", help="Action: show, set, add-endpoint"),
    key: str | None = typer.Argument(None, help="Config key (for 'set')"),
    value: str | None = typer.Argument(None, help="Config value (for 'set')"),
):
    """View or modify configuration."""
    settings = _load_settings()

    if action == "show":
        _config_show(settings)
    elif action == "set":
        if not key or value is None:
            console.print("[red]Usage: agent-scout config set <key> <value>[/red]")
            raise typer.Exit(1)
        _config_set(settings, key, value)
    elif action == "add-endpoint":
        _config_add_endpoint(settings)
    else:
        console.print(f"[red]Unknown action: {action}[/red]")
        raise typer.Exit(1)


def _config_show(settings: Settings) -> None:
    """Display current configuration."""
    table = Table(title="AgentScout Configuration")
    table.add_column("Setting", style="cyan")
    table.add_column("Value", style="white")

    table.add_row("Default model", settings.llm.default_model)
    table.add_row("Fast model", settings.llm.fast_model)
    table.add_row("Best model", settings.llm.best_model)
    table.add_row("Temperature", str(settings.llm.temperature))
    table.add_row("Max tokens", str(settings.llm.max_tokens))
    table.add_row("Smart routing", str(settings.llm.enable_routing))
    table.add_row("---", "---")
    table.add_row("Task budget", f"${settings.budget.task_limit}")
    table.add_row("Daily budget", f"${settings.budget.daily_limit}")
    table.add_row("Monthly budget", f"${settings.budget.monthly_limit}")
    table.add_row("Enforce budgets", str(settings.budget.enforce))
    table.add_row("---", "---")
    table.add_row("Personality", settings.personality)
    table.add_row("Autonomy", settings.autonomy)
    table.add_row("Plugins", ", ".join(settings.plugins))
    table.add_row("---", "---")
    table.add_row("Tavily key", "***" if settings.search.tavily_api_key else "(not set)")
    table.add_row("SerpAPI key", "***" if settings.search.serpapi_api_key else "(not set)")
    table.add_row("Brave key", "***" if settings.search.brave_api_key else "(not set)")

    if settings.custom_endpoints:
        table.add_row("---", "---")
        for ep in settings.custom_endpoints:
            table.add_row(f"Endpoint: {ep.name}", f"{ep.base_url} ({ep.model_name})")

    console.print(table)
    console.print(f"\n[dim]Config file: {DEFAULT_CONFIG_FILE}[/dim]")


def _config_set(settings: Settings, key: str, value: str) -> None:
    """Set a single config value."""
    parts = key.split(".")
    try:
        if len(parts) == 2:
            section, field = parts
            obj = getattr(settings, section, None)
            if obj is None:
                console.print(f"[red]Unknown section: {section}[/red]")
                raise typer.Exit(1)
            if not hasattr(obj, field):
                console.print(f"[red]Unknown field: {section}.{field}[/red]")
                raise typer.Exit(1)
            current = getattr(obj, field)
            # Type coercion
            if isinstance(current, bool):
                setattr(obj, field, value.lower() in ("true", "1", "yes"))
            elif isinstance(current, float):
                setattr(obj, field, float(value))
            elif isinstance(current, int):
                setattr(obj, field, int(value))
            else:
                setattr(obj, field, value)
        elif len(parts) == 1:
            if not hasattr(settings, key):
                console.print(f"[red]Unknown key: {key}[/red]")
                raise typer.Exit(1)
            setattr(settings, key, value)
        else:
            console.print(f"[red]Invalid key format: {key}[/red]")
            raise typer.Exit(1)

        save_settings(settings)
        console.print(f"[green]Set {key} = {value}[/green]")

    except (ValueError, TypeError) as e:
        console.print(f"[red]Invalid value: {e}[/red]")
        raise typer.Exit(1) from e


def _config_add_endpoint(settings: Settings) -> None:
    """Interactively add a custom endpoint."""
    ep = CustomEndpointSettings(
        name=Prompt.ask("Endpoint name"),
        base_url=Prompt.ask("Base URL"),
        api_key=Prompt.ask("API key"),
        model_name=Prompt.ask("Model name"),
    )
    settings.custom_endpoints.append(ep)
    save_settings(settings)
    console.print(f"[green]Added endpoint '{ep.name}'[/green]")


# ---- history ----


@app.command()
def history(
    task_id: str | None = typer.Argument(None, help="Task ID to view details"),
    search: str | None = typer.Option(None, "--search", "-s", help="Search task descriptions"),
    export_format: str | None = typer.Option(
        None, "--export", "-e", help="Export format: json, markdown, csv"
    ),
):
    """View task history."""
    console.print("[bold]Task History[/bold]")

    from agent_scout.config.settings import DEFAULT_CONFIG_DIR
    from agent_scout.db.database import Database

    db_path = Path(DEFAULT_CONFIG_DIR) / "agent_scout.db"

    if not db_path.exists():
        console.print("[dim]No task history yet. Run a task first![/dim]")
        return

    async def _show_history() -> None:
        db = Database(str(db_path))
        await db.connect()
        try:
            tasks = await db.list_tasks()

            if search:
                tasks = [t for t in tasks if search.lower() in t.description.lower()]

            if task_id:
                task = await db.get_task(task_id)
                if task:
                    _display_task_detail(task)
                else:
                    console.print(f"[red]Task '{task_id}' not found[/red]")
                return

            if not tasks:
                console.print("[dim]No tasks found.[/dim]")
                return

            table = Table(title="Task History")
            table.add_column("ID", style="cyan", max_width=12)
            table.add_column("Description", max_width=50)
            table.add_column("Status", style="bold")
            table.add_column("Created")

            for t in tasks[:50]:
                status_color = {
                    "completed": "green",
                    "failed": "red",
                    "executing": "yellow",
                }.get(t.status.value, "white")

                import time

                created = time.strftime("%Y-%m-%d %H:%M", time.localtime(t.created_at))
                table.add_row(
                    t.id[:12],
                    t.description[:50],
                    f"[{status_color}]{t.status.value}[/{status_color}]",
                    created,
                )

            console.print(table)
        finally:
            await db.disconnect()

    asyncio.run(_show_history())


def _display_task_detail(task) -> None:  # noqa: ANN001
    """Display detailed task information."""
    import time

    created = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(task.created_at))
    updated = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(task.updated_at))

    console.print(
        Panel(
            f"[bold]ID:[/bold] {task.id}\n"
            f"[bold]Description:[/bold] {task.description}\n"
            f"[bold]Status:[/bold] {task.status.value}\n"
            f"[bold]Created:[/bold] {created}\n"
            f"[bold]Updated:[/bold] {updated}\n"
            f"[bold]Result:[/bold] {task.result or '(none)'}\n"
            f"[bold]Error:[/bold] {task.error or '(none)'}",
            title="[bold]Task Detail[/bold]",
        )
    )


# ---- schedule ----


@app.command()
def schedule(
    action: str = typer.Argument("list", help="Action: list, add, remove"),
    schedule_id: str | None = typer.Argument(None, help="Schedule ID (for remove)"),
    task_desc: str | None = typer.Option(None, "--task", "-t", help="Task description"),
    cron: str | None = typer.Option(None, "--cron", "-c", help="Cron expression"),
):
    """Manage scheduled tasks."""
    if action == "list":
        console.print("[bold]Scheduled Tasks[/bold]")
        console.print("[dim]No scheduled tasks. Add one with:[/dim]")
        console.print(
            '[dim]agent-scout schedule add --task "Check prices" --cron "0 8 * * *"[/dim]'
        )
    elif action == "add":
        if not task_desc or not cron:
            console.print("[red]Usage: agent-scout schedule add --task '...' --cron '...'[/red]")
            raise typer.Exit(1)
        console.print(f"[green]Scheduled: '{task_desc}' with cron '{cron}'[/green]")
        console.print("[yellow]Note: Scheduling persistence coming in Phase 7[/yellow]")
    elif action == "remove":
        if not schedule_id:
            console.print("[red]Usage: agent-scout schedule remove <schedule-id>[/red]")
            raise typer.Exit(1)
        console.print(f"[green]Removed schedule '{schedule_id}'[/green]")
    else:
        console.print(f"[red]Unknown action: {action}[/red]")
        raise typer.Exit(1)


# ---- status ----


@app.command()
def status():
    """Show agent status and cost summary."""
    settings = _load_settings()

    console.print(
        Panel(
            f"[bold]Model:[/bold] {settings.llm.default_model}\n"
            f"[bold]Routing:[/bold] {'enabled' if settings.llm.enable_routing else 'disabled'}\n"
            f"[bold]Autonomy:[/bold] {settings.autonomy}\n"
            f"[bold]Budget:[/bold] ${settings.budget.task_limit}/task, "
            f"${settings.budget.daily_limit}/day, "
            f"${settings.budget.monthly_limit}/month\n"
            f"[bold]Plugins:[/bold] {', '.join(settings.plugins)}",
            title="[bold green]AgentScout Status[/bold green]",
            border_style="green",
        )
    )


# ---- version ----


@app.command()
def version():
    """Show version information."""
    console.print(f"[bold]AgentScout[/bold] CLI v{cli_version} | Core v{core_version}")


if __name__ == "__main__":
    app()
