"""Fuzzy-search command palette for the ALiCE TUI."""

from __future__ import annotations

from typing import TYPE_CHECKING

from textual.binding import Binding
from textual.containers import Vertical
from textual.screen import ModalScreen
from textual.widgets import Input, OptionList, Static
from textual.widgets.option_list import Option

from alice_cli.tui.screens.home import _SCREEN_VERBS, VERB_LIST

if TYPE_CHECKING:
    from textual.app import ComposeResult


# Short descriptions for each verb shown in the palette.
_VERB_DESCRIPTIONS: dict[str, str] = {
    "auth": "Authenticate with AWS SSO",
    "chat": "Multi-turn conversation with a model",
    "compose": "Agent compose wizard",
    "dialog": "Two-model debate",
    "invoke": "Send a single prompt to a model",
    "summarize": "Summarize text or a file",
    "appraise": "Appraise session quality",
    "batch": "Batch process prompts",
    "compare": "Compare responses from multiple models",
    "recall": "Browse past sessions",
    "get-secret": "Retrieve a secret from Secrets Manager",  # pragma: allowlist secret
    "list-models": "List available Bedrock models",
    "list-aliases": "List model aliases",
    "list-secrets": "List secrets in Secrets Manager",  # pragma: allowlist secret
    "diagnose": "Diagnose AWS connectivity",
    "config": "Show current configuration",
    "status": "Show authentication status",
}


def fuzzy_match(query: str, items: list[str]) -> list[str]:
    """Return items that contain query as a case-insensitive substring."""
    if not query:
        return list(items)
    q = query.lower()
    return [item for item in items if q in item.lower()]


def _make_option_label(verb: str) -> str:
    """Build a Rich-formatted label for a verb entry in the option list."""
    badge = "[#00CC66] TUI [/]" if verb in _SCREEN_VERBS else "[#805800] CLI-only [/]"
    desc = _VERB_DESCRIPTIONS.get(verb, "")
    return f"{badge}  [bold]{verb}[/]  [dim]{desc}[/]"


class CommandPalette(ModalScreen[str | None]):
    """Fuzzy-search overlay for navigating to screens and actions."""

    BINDINGS = [
        Binding("escape", "dismiss_palette", "Close", show=False),
    ]

    DEFAULT_CSS = """
    CommandPalette {
        align: center middle;
    }

    #palette-dialog {
        width: 64;
        height: auto;
        max-height: 80%;
        background: #0A1628;
        border: tall #1A3A5C;
        padding: 1 2;
    }

    #palette-title {
        text-align: center;
        color: #FFD866;
        text-style: bold;
        width: 100%;
        padding-bottom: 1;
        background: transparent;
    }

    #palette-input {
        margin-bottom: 1;
    }

    #palette-options {
        height: auto;
        max-height: 20;
        background: #0A1628;
    }

    #palette-hint {
        text-align: center;
        color: #805800;
        width: 100%;
        padding-top: 1;
        background: transparent;
    }
    """

    def compose(self) -> ComposeResult:
        with Vertical(id="palette-dialog"):
            yield Static("⌘  Command Palette", id="palette-title")
            yield Input(placeholder="Type to search…", id="palette-input")
            yield OptionList(*self._build_options(VERB_LIST), id="palette-options")
            yield Static("Esc to close · Enter to select", id="palette-hint")

    def on_mount(self) -> None:
        """Focus the search input when the palette opens."""
        self.query_one("#palette-input", Input).focus()

    def on_input_changed(self, event: Input.Changed) -> None:
        """Filter the option list as the user types."""
        query = event.value
        filtered = fuzzy_match(query, VERB_LIST)
        option_list = self.query_one("#palette-options", OptionList)
        option_list.clear_options()
        option_list.add_options(self._build_options(filtered))

    def on_option_list_option_selected(self, event: OptionList.OptionSelected) -> None:
        """Handle selection of a verb from the list."""
        # The option id stores the verb name
        verb = event.option.id
        if verb is None:
            return
        self.dismiss(verb)

    def action_dismiss_palette(self) -> None:
        """Close the palette returning None."""
        self.dismiss(None)

    @staticmethod
    def _build_options(verbs: list[str]) -> list[Option]:
        """Build OptionList options from a list of verb names."""
        return [Option(_make_option_label(verb), id=verb) for verb in verbs]
