from __future__ import annotations

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


class UserResult(ListItem):
    def __init__(self, user: dict) -> None:
        super().__init__()
        self.user_data = user

    def compose(self) -> ComposeResult:
        u = self.user_data
        name = u.get("display_name") or u.get("username", "?")
        username = u.get("username", "")
        online = u.get("is_online", False)
        dot = "[green]\u2022[/] " if online else "[dim]\u2022[/] "
        yield Static(f"{dot}{name} [dim]@{username}[/]")


class NewChatScreen(ModalScreen[dict | None]):

    def __init__(self) -> None:
        super().__init__()
        self._debounce_timer: Timer | None = None

    def compose(self) -> ComposeResult:
        with Vertical(id="new-chat-modal"):
            yield Label("new conversation", id="modal-title")
            yield Input(placeholder="search users...", id="user-search")
            yield ListView(id="user-results")

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

    def on_key(self, event: Key) -> None:
        if event.key == "escape":
            event.stop()
            event.prevent_default()
            self.dismiss(None)
        elif event.key == "down":
            lv = self.query_one("#user-results", ListView)
            if lv.children:
                lv.focus()
        elif event.key == "up":
            focused = self.app.focused
            lv = self.query_one("#user-results", ListView)
            if focused is lv or (focused and focused.parent is lv):
                if lv.index == 0:
                    self.query_one("#user-search", Input).focus()

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

    @work(exclusive=True)
    async def _search(self, query: str) -> None:
        results_view = self.query_one("#user-results", ListView)
        await results_view.clear()

        if not query.strip():
            return

        api = self.app.api
        try:
            users = await api.search_users(query.strip())
        except Exception:
            users = []

        for user in users:
            await results_view.append(UserResult(user))

    @on(ListView.Selected, "#user-results")
    def on_user_selected(self, event: ListView.Selected) -> None:
        item = event.item
        if isinstance(item, UserResult):
            self._create_dm(item.user_data)

    @work(exclusive=True)
    async def _create_dm(self, user: dict) -> None:
        api = self.app.api
        try:
            conv = await api.create_conversation("dm", [user["id"]])
            self.dismiss(conv)
        except Exception as exc:
            self.notify(f"Error: {exc}", severity="error")
