"""Model picker widget with search and multi-select.

A search input that uses the ApiClient to fetch models on each keystroke,
displaying results in a static list below. Users can select multiple
models (primary + fallbacks) using Space or Enter.
"""

from typing import Any

from textual import on
from textual.message import Message
from textual.widgets import OptionList

from alloy_runtime_sdk.api_client.client import ApiClient
from alloy_runtime_types.dtos.models import ModelListItemResponse

from cli.infrastructure.forms.base_picker import MultiSelectPicker


class ModelPicker(MultiSelectPicker[ModelListItemResponse]):
    """Multi-select model picker with live search.

    Uses the ApiClient to fetch models on each keystroke. Results appear in a
    static box below the search input.

    Usage:
        yield ModelPicker(
            client=server_client,
            id="models"
        )

        # Get selected models
        picker = self.query_one("#models", ModelPicker)
        models = picker.selected_models  # List[ModelListItemResponse]

    Keybindings:
        - Type to search (fetches from API)
        - Up/Down to navigate results
        - Space or Enter to select/deselect
    """

    class ModelsChanged(Message):
        """Posted when selected models change."""

        def __init__(self, models: list[ModelListItemResponse]) -> None:
            self.models = models
            super().__init__()

    def __init__(
        self,
        client: ApiClient,
        placeholder: str = "Type to search models (e.g., gpt-4, claude, sonnet)...",
        **kwargs: Any,
    ) -> None:
        """Initialize the model picker.

        Args:
            client: ApiClient instance for API calls
            placeholder: Placeholder text for search input
        """
        super().__init__(
            client=client,
            placeholder=placeholder,
            empty_message="No models selected",
            **kwargs,
        )

    @property
    def selected_models(self) -> list[ModelListItemResponse]:
        """Get the list of selected models in order (primary first, then fallbacks)."""
        return self.selected_items

    async def _fetch_items(self, query: str) -> list[ModelListItemResponse]:
        """Fetch models matching query from the API."""
        response = await self._client.list_models(
            search=query,
            configured_only=True,
            limit=100,
        )
        return list(response.models)

    def _format_item(self, item: ModelListItemResponse) -> str:
        """Format model for display in option list."""
        return f"{item.provider_key}:{item.provider_model_name}"

    def _get_item_id(self, item: ModelListItemResponse) -> str:
        """Get unique identifier for a model."""
        return f"{item.provider_key}:{item.provider_model_name}"

    def _get_result_count_message(self, count: int) -> str:
        """Get status message for result count."""
        if count == 0:
            return "No models found"
        return f"{count} model{'s' if count != 1 else ''} found - Space/Enter to select"

    def _format_selection_display(self) -> str | None:
        """Format selected models as an ordered list."""
        if not self._selected_items:
            return None

        lines: list[str] = []
        for i, model in enumerate(self._selected_items.values()):
            model_label = f"{model.provider_key}:{model.provider_model_name}"
            if i == 0:
                lines.append(f"[bold green]1. {model_label}[/] (primary)")
            else:
                lines.append(f"{i + 1}. {model_label}")
        return "\n".join(lines)

    def _post_selection_changed(self) -> None:
        """Post ModelsChanged message instead of generic SelectionChanged."""
        self.post_message(self.ModelsChanged(self.selected_models))

    def on_key(self, event: Any) -> None:
        """Handle space key to toggle selection."""
        if event.key == "space":
            options = self.query_one("#search-options", OptionList)
            if options.highlighted is not None:
                self._handle_item_selection(options.highlighted)
                event.prevent_default()
                event.stop()

    @on(OptionList.OptionHighlighted, "#search-options")
    def on_option_highlighted(self, event: OptionList.OptionHighlighted) -> None:
        """Handle highlighting - space key handling is done via on_key."""
        pass

    def set_initial_models(self, models: list[ModelListItemResponse]) -> None:
        """Pre-populate the picker with existing model selections.

        Args:
            models: List of ModelListItemResponse objects to pre-select
        """
        self.set_initial_selections(models)
