"""Signals screen: DataTable of market signals with filter, refresh, and detail."""

from datetime import date

from textual import work
from textual.app import ComposeResult
from textual.binding import Binding
from textual.containers import Vertical
from textual.widgets import DataTable, Input, Static

from skilark_cli.client import SkilarkClient

_SIGNAL_ICONS: dict[str, str] = {
    "company_surge": "📈",
    "salary_insight": "💰",
    "company_layoff": "📉",
    "company_news": "📰",
    "sec_workforce_filing": "📋",
}


def _signal_icon(signal_type: str) -> str:
    return _SIGNAL_ICONS.get(signal_type, "📊")


class SignalsPane(Vertical):
    """Market signals table with detail panel."""

    BINDINGS = [
        Binding("slash", "start_filter", "/ Filter", show=True),
        Binding("r", "refresh", "Refresh", show=True),
        Binding("escape", "clear_filter", "Close", show=False),
    ]

    def __init__(self, client: SkilarkClient | None = None) -> None:
        super().__init__()
        self.client = client
        self._signals: list[dict] = []
        self._week_of = ""
        self._filter_text = ""
        self._selected_index: int | None = None

    def compose(self) -> ComposeResult:
        yield Static("", id="signals-header")
        yield Input(
            placeholder="Type to filter...",
            id="filter-input",
            disabled=True,
        )
        yield DataTable(id="signals-table")
        yield Static("", id="signals-detail")

    def on_mount(self) -> None:
        filter_input = self.query_one("#filter-input", Input)
        filter_input.display = False

        table = self.query_one("#signals-table", DataTable)
        table.cursor_type = "row"
        table.add_columns("Type", "Subject", "Detail")

        self._load_signals()

    @work(thread=True, exit_on_error=False)
    def _load_signals(self) -> None:
        if not self.client:
            self.app.call_from_thread(self._render_empty, "No API client configured.")
            return
        try:
            data = self.client.get_signals(limit=0)
        except Exception as e:
            self.app.call_from_thread(self._render_empty, f"Error: {e}")
            return
        self.app.call_from_thread(self._on_data_loaded, data)

    def _on_data_loaded(self, data: dict) -> None:
        if not self.is_attached:
            return
        self._signals = data.get("signals", [])
        self._week_of = data.get("week_of", "")
        self._render_table()

    def _render_empty(self, message: str) -> None:
        if not self.is_attached:
            return
        header = self.query_one("#signals-header", Static)
        header.update(f"[bold]Market Signals[/bold]\n\n[dim]{message}[/dim]")

    def _render_table(self) -> None:
        header = self.query_one("#signals-header", Static)
        week_label = self._format_week(self._week_of)
        count = len(self._filtered_signals())
        total = len(self._signals)
        if self._filter_text:
            header.update(
                f"[bold]Market Signals[/bold] -- Week of {week_label}  "
                f"({count}/{total} shown)"
            )
        else:
            header.update(
                f"[bold]Market Signals[/bold] -- Week of {week_label}  "
                f"({total} signals)"
            )

        table = self.query_one("#signals-table", DataTable)
        table.clear()

        for signal in self._filtered_signals():
            signal_type = signal.get("type", signal.get("signal_type", ""))
            icon = _signal_icon(signal_type)
            title = signal.get("title", "")
            body = signal.get("body", "")
            short_body = body[:60] + "..." if len(body) > 60 else body
            table.add_row(f"{icon}", title, short_body)

        detail = self.query_one("#signals-detail", Static)
        detail.update("")
        self._selected_index = None

    def _filtered_signals(self) -> list[dict]:
        if not self._filter_text:
            return self._signals
        q = self._filter_text.lower()
        return [
            s
            for s in self._signals
            if q in s.get("title", "").lower()
            or q in s.get("body", "").lower()
            or q in s.get("type", s.get("signal_type", "")).lower()
        ]

    def on_data_table_row_highlighted(self, event: DataTable.RowHighlighted) -> None:
        if event.cursor_row is None:
            return
        filtered = self._filtered_signals()
        if 0 <= event.cursor_row < len(filtered):
            self._selected_index = event.cursor_row
            signal = filtered[event.cursor_row]
            self._show_detail(signal)

    def _show_detail(self, signal: dict) -> None:
        detail = self.query_one("#signals-detail", Static)
        title = signal.get("title", "")
        body = signal.get("body", "")
        signal_type = signal.get("type", signal.get("signal_type", ""))
        icon = _signal_icon(signal_type)
        detail.update(
            f"\n{icon} [bold]{title}[/bold]\n{body}\n"
        )

    def action_start_filter(self) -> None:
        filter_input = self.query_one("#filter-input", Input)
        filter_input.disabled = False
        filter_input.display = True
        filter_input.focus()

    def action_clear_filter(self) -> None:
        filter_input = self.query_one("#filter-input", Input)
        filter_input.display = False
        filter_input.disabled = True
        filter_input.value = ""
        self._filter_text = ""
        self._render_table()
        self.query_one("#signals-table", DataTable).focus()

    def on_input_changed(self, event: Input.Changed) -> None:
        if event.input.id == "filter-input":
            self._filter_text = event.value
            self._render_table()

    def on_input_submitted(self, event: Input.Submitted) -> None:
        if event.input.id == "filter-input":
            filter_input = self.query_one("#filter-input", Input)
            filter_input.display = False
            filter_input.disabled = True
            self.query_one("#signals-table", DataTable).focus()

    def action_refresh(self) -> None:
        self._filter_text = ""
        filter_input = self.query_one("#filter-input", Input)
        filter_input.value = ""
        filter_input.display = False
        filter_input.disabled = True
        header = self.query_one("#signals-header", Static)
        header.update("[bold]Market Signals[/bold]\n\n[dim]Loading...[/dim]")
        self._load_signals()

    @staticmethod
    def _format_week(week_of: str) -> str:
        if not week_of:
            return "unknown"
        try:
            d = date.fromisoformat(week_of)
            return f"{d.strftime('%b')} {d.day}"
        except (ValueError, TypeError):
            return week_of
