"""Combined channel values table.

A single DataTable showing all channel information for plotted channels:
- #: sequential channel number
- ISO Code: fixed-width channel code
- Description: flex column, fills remaining space
- Unit: engineering unit
- Min @ Time, Max @ Time: peak statistics with time of occurrence
- X1, X2: interpolated values at locked cursor positions
- Cursor: live interpolated value at mouse hover position
"""

from __future__ import annotations

from typing import Any

import numpy as np

import dash_bootstrap_components as dbc
from dash import dash_table, dcc, html

from impakt.channel.model import Channel


def build_channel_values_panel() -> dbc.Card:
    """Build the combined channel values panel."""
    return dbc.Card(
        [
            dbc.CardHeader(
                [
                    html.Span("Channel Values", className="fw-bold"),
                    html.Span(
                        " — hover over plot for live cursor",
                        className="text-muted",
                        style={"fontSize": "10px", "fontWeight": "normal"},
                    ),
                ],
                className="py-1",
            ),
            dbc.CardBody(
                [
                    # X1/X2 lock controls
                    dbc.Row(
                        [
                            dbc.Col(
                                [
                                    dbc.InputGroup(
                                        [
                                            dbc.InputGroupText(
                                                "X1",
                                                style={"fontSize": "11px", "padding": "2px 6px"},
                                            ),
                                            dbc.Input(
                                                id="cursor-x1",
                                                type="number",
                                                step=0.0001,
                                                value=0.0,
                                                size="sm",
                                                style={
                                                    "fontSize": "11px",
                                                    "fontFamily": "monospace",
                                                },
                                            ),
                                            dbc.InputGroupText(
                                                "s",
                                                style={"fontSize": "11px", "padding": "2px 4px"},
                                            ),
                                        ],
                                        size="sm",
                                    ),
                                ],
                                width=6,
                            ),
                            dbc.Col(
                                [
                                    dbc.InputGroup(
                                        [
                                            dbc.InputGroupText(
                                                "X2",
                                                style={"fontSize": "11px", "padding": "2px 6px"},
                                            ),
                                            dbc.Input(
                                                id="cursor-x2",
                                                type="number",
                                                step=0.0001,
                                                value=0.1,
                                                size="sm",
                                                style={
                                                    "fontSize": "11px",
                                                    "fontFamily": "monospace",
                                                },
                                            ),
                                            dbc.InputGroupText(
                                                "s",
                                                style={"fontSize": "11px", "padding": "2px 4px"},
                                            ),
                                        ],
                                        size="sm",
                                    ),
                                ],
                                width=6,
                            ),
                        ],
                        className="mb-1",
                    ),
                    # Combined DataTable
                    dash_table.DataTable(
                        id="channel-values-grid",
                        columns=[
                            {"name": "#", "id": "ch_num", "type": "numeric"},
                            {"name": "ISO Code", "id": "iso_code"},
                            {"name": "Description", "id": "description"},
                            {"name": "Unit", "id": "unit"},
                            {"name": "Min", "id": "min", "type": "numeric"},
                            {"name": "@ Time", "id": "min_time"},
                            {"name": "Max", "id": "max", "type": "numeric"},
                            {"name": "@ Time", "id": "max_time"},
                            {"name": "X1", "id": "x1", "type": "numeric"},
                            {"name": "X2", "id": "x2", "type": "numeric"},
                            {"name": "Cursor", "id": "cursor", "type": "numeric"},
                        ],
                        data=[],
                        style_table={
                            "overflowY": "auto",
                            "overflowX": "auto",
                            "maxHeight": "250px",
                        },
                        style_header={
                            "backgroundColor": "#f8f9fa",
                            "fontWeight": "bold",
                            "fontSize": "10px",
                            "padding": "3px 6px",
                            "borderBottom": "2px solid #dee2e6",
                            "whiteSpace": "nowrap",
                        },
                        # Force table-layout:fixed so explicit widths are respected
                        # and Description gets whatever space remains.
                        css=[
                            {
                                "selector": ("#channel-values-grid table"),
                                "rule": "table-layout: fixed; width: 100%;",
                            }
                        ],
                        style_cell={
                            "fontSize": "11px",
                            "fontFamily": "'SF Mono', 'Menlo', 'Monaco', monospace",
                            "padding": "2px 6px",
                            "border": "none",
                            "borderBottom": "1px solid #f0f0f0",
                            "overflow": "hidden",
                            "textOverflow": "ellipsis",
                            "whiteSpace": "nowrap",
                        },
                        style_cell_conditional=[
                            # Fixed-width columns (percentages sum to ~74%, leaving ~26% for Description)
                            {
                                "if": {"column_id": "ch_num"},
                                "width": "3%",
                                "textAlign": "right",
                                "color": "#999",
                            },
                            {"if": {"column_id": "iso_code"}, "width": "5%"},
                            {
                                "if": {"column_id": "description"},
                                "fontFamily": "inherit",
                                "textAlign": "left",
                            },
                            {"if": {"column_id": "unit"}, "width": "2%", "textAlign": "center"},
                            {"if": {"column_id": "min"}, "width": "8%", "textAlign": "right"},
                            {
                                "if": {"column_id": "min_time"},
                                "width": "7%",
                                "textAlign": "right",
                                "color": "#999",
                            },
                            {"if": {"column_id": "max"}, "width": "8%", "textAlign": "right"},
                            {
                                "if": {"column_id": "max_time"},
                                "width": "7%",
                                "textAlign": "right",
                                "color": "#999",
                            },
                            {"if": {"column_id": "x1"}, "width": "8%", "textAlign": "right"},
                            {"if": {"column_id": "x2"}, "width": "8%", "textAlign": "right"},
                            {"if": {"column_id": "cursor"}, "width": "8%", "textAlign": "right"},
                        ],
                        style_data_conditional=[],
                        style_as_list_view=True,
                        fixed_rows={"headers": True},
                        sort_action="native",
                    ),
                    # Interval that polls the JS-side hover X position
                    dcc.Interval(id="cursor-poll-interval", interval=80, n_intervals=0),
                    # Hidden store for the current hover X position
                    dcc.Store(id="cursor-hover-x", data=None),
                ],
                className="py-1 px-2",
            ),
        ]
    )


def build_channel_values_data(
    channels: list[tuple[str, Channel]],
    hover_x: float | None,
    x1: float,
    x2: float,
) -> list[dict[str, Any]]:
    """Build combined channel values rows.

    Each row contains identity, statistics, and cursor values for one channel.
    """
    rows: list[dict[str, Any]] = []
    for idx, (label, ch) in enumerate(channels):
        data = ch.data

        min_val = float(np.min(data))
        min_idx = int(np.argmin(data))
        max_val = float(np.max(data))
        max_idx = int(np.argmax(data))

        cursor_val = f"{ch.value_at(hover_x):.4f}" if hover_x is not None else ""

        rows.append(
            {
                "ch_num": idx + 1,
                "iso_code": ch.name,
                "description": label,
                "unit": ch.unit,
                "min": f"{min_val:.4f}",
                "min_time": f"{float(ch.time[min_idx]):.4f}",
                "max": f"{max_val:.4f}",
                "max_time": f"{float(ch.time[max_idx]):.4f}",
                "x1": f"{ch.value_at(x1):.4f}",
                "x2": f"{ch.value_at(x2):.4f}",
                "cursor": cursor_val,
            }
        )
    return rows
