"""Common logic for generating table widgets."""

import logging
from collections.abc import Callable
from typing import Any

from nicegui import events, ui

logger = logging.getLogger(__name__)


def _extract_row_id(args: Any) -> str | None:
    if isinstance(args, list) and len(args) > 1 and isinstance(args[1], dict):
        return str(args[1].get("id")) if args[1].get("id") is not None else None

    if isinstance(args, dict):
        row = args.get("row")
        if isinstance(row, dict) and "id" in row:
            return str(row["id"])
        if "id" in args:
            return str(args["id"])

    return None


def _bind_row_click_handler(
    table: Any,
    *,
    on_row_click_id: Callable[[str], None],
) -> None:
    def handle_row_click(event: events.GenericEventArguments) -> None:
        row_id = _extract_row_id(event.args)
        if row_id is None:
            return
        on_row_click_id(row_id)

    table.on("rowClick", handle_row_click)


def build_table(
    rows: list[dict[str, Any]],
    columns: list[dict[str, Any]],
    *,
    default_sort_by: str | None = None,
    default_descending: bool = False,
    classes: str = "",
    show_search: bool = True,
    search_placeholder: str = "Search records...",
    on_row_click_id: Callable[[str], None] | None = None,
) -> Any:
    """Build a styled Quasar table widget with optional client-side filtering and row-click handlers."""
    pagination: dict[str, Any] = {"rowsPerPage": 25}
    if default_sort_by is not None:
        pagination["sortBy"] = default_sort_by
        pagination["descending"] = default_descending

    # Use a parent container to hold both the search bar and the table seamlessly
    with ui.column().classes("w-full gap-2"):
        if show_search:
            with ui.row().classes("w-full items-center justify-end"):
                search_input = (
                    ui.input(placeholder=search_placeholder)
                    .props("dense outlined clearable icon=search")
                    .classes("w-64 text-xs bg-white")
                )

        table = (
            ui.table(
                rows=rows,
                columns=columns,
                row_key="id",
                pagination=pagination,
            )
            .classes(f"w-full ui-table {classes}".strip())
            .props(
                'flat square binary-state-sort table-style="table-layout: fixed; width: 100%;" '
                'header-cell-class="ui-table-header text-xs uppercase tracking-wider" '
                'table-class="ui-table-body text-xs"'
            )
        )

        # Bind client-side text filter if search input is active
        if show_search:
            table.bind_filter_from(search_input, "value")

    if on_row_click_id is not None:
        _bind_row_click_handler(table, on_row_click_id=on_row_click_id)

    return table