from __future__ import annotations

from textual import on, work
from textual.app import ComposeResult
from textual.containers import Vertical, VerticalScroll
from textual.events import Key
from textual.screen import ModalScreen
from textual.timer import Timer
from textual.widgets import Input, Label, Static


class SearchResultItem(Static):
    def __init__(self, msg: dict) -> None:
        self.msg_data = msg
        sender = msg.get("sender_display_name") or msg.get("sender_username", "?")
        content = msg.get("content", "").replace("\n", " ")
        if len(content) > 80:
            content = content[:77] + "..."
        ts = msg.get("created_at", "")[:10]
        # Escape Rich markup
        sender = sender.replace("[", "\\[")
        content = content.replace("[", "\\[")
        super().__init__(
            f"[bold]{sender}[/] [dim]{ts}[/]\n{content}",
            classes="search-result",
        )


class SearchScreen(ModalScreen[dict | None]):
    """Search messages in a conversation."""

    def __init__(self, conversation_id: str) -> None:
        super().__init__()
        self._conversation_id = conversation_id
        self._debounce_timer: Timer | None = None

    def compose(self) -> ComposeResult:
        with Vertical(id="search-modal"):
            yield Label("SEARCH MESSAGES", id="modal-title")
            yield Input(placeholder="search...", id="search-input")
            yield Label("", id="search-count")
            yield VerticalScroll(id="search-results")

    def on_mount(self) -> None:
        self.query_one("#search-input", Input).focus()

    def on_key(self, event: Key) -> None:
        if event.key == "escape":
            event.stop()
            event.prevent_default()
            self.dismiss(None)

    @on(Input.Changed, "#search-input")
    def on_search_changed(self, event: Input.Changed) -> None:
        if self._debounce_timer:
            self._debounce_timer.stop()
        self._debounce_timer = self.set_timer(
            0.4, lambda: self._search(event.value)
        )

    @work(exclusive=True)
    async def _search(self, query: str) -> None:
        results_container = self.query_one("#search-results", VerticalScroll)
        count_label = self.query_one("#search-count", Label)
        await results_container.remove_children()

        if not query.strip() or len(query.strip()) < 2:
            count_label.update("")
            return

        try:
            api = self.app.api
            results = await api.search_messages(self._conversation_id, query.strip())
        except Exception:
            count_label.update("[dim]search failed[/]")
            return

        count_label.update(f"[dim]{len(results)} result{'s' if len(results) != 1 else ''}[/]")

        for msg in results:
            await results_container.mount(SearchResultItem(msg))
