"""Channel values table callbacks.

Updates the combined channel values DataTable with statistics and
live cursor values as the user moves the mouse over the plot.
Row colors match the plot trace colors.
"""

from __future__ import annotations

from typing import Any

import dash
from dash import Input, Output, State, html
from dash.exceptions import PreventUpdate

from impakt.plot.engine import DEFAULT_COLORS
from impakt.web.callbacks.plot_callbacks import _resolve_channels
from impakt.web.components.channel_values import build_channel_values_data
from impakt.web.state import AppState


def register_cursor_callbacks(app: dash.Dash, app_state: AppState) -> None:
    """Register channel values table callbacks."""

    # Clientside callback: reads window.__impakt_hover_x (set by cursor_tracker.js)
    app.clientside_callback(
        """
        function(n_intervals) {
            var x = window.__impakt_hover_x;
            if (x !== undefined && x !== null && !isNaN(x)) {
                return x;
            }
            return window.dash_clientside.no_update;
        }
        """,
        Output("cursor-hover-x", "data"),
        Input("cursor-poll-interval", "n_intervals"),
    )

    @app.callback(
        Output("channel-values-grid", "data"),
        [
            Input("cursor-hover-x", "data"),
            Input("cursor-x1", "value"),
            Input("cursor-x2", "value"),
            Input("selected-channels-store", "data"),
            Input("cfc-select", "value"),
            Input("y-align-check", "value"),
            Input("channel-overrides-store", "data"),
        ],
        [
            State("x-align-method", "value"),
            State("x-align-value", "value"),
            State("show-resultant", "value"),
        ],
    )
    def update_channel_values_data(
        hover_x: float | None,
        cursor_x1: float | None,
        cursor_x2: float | None,
        selected_keys: list[str] | None,
        cfc_value: str,
        y_align: bool,
        channel_overrides: dict | None,
        x_align_method: str,
        x_align_value: float | None,
        show_resultant: bool,
    ) -> list[dict[str, str]]:
        if not selected_keys:
            return []

        channels = _resolve_channels(
            selected_keys,
            app_state,
            cfc_value,
            y_align,
            x_align_method or "none",
            x_align_value,
            show_resultant,
        )

        if not channels:
            return []

        x1 = cursor_x1 if cursor_x1 is not None else 0.0
        x2 = cursor_x2 if cursor_x2 is not None else 0.1

        return build_channel_values_data(channels, hover_x, x1, x2)

    @app.callback(
        Output("channel-values-grid", "style_data_conditional"),
        [Input("selected-channels-store", "data")],
        [
            State("cfc-select", "value"),
            State("y-align-check", "value"),
            State("x-align-method", "value"),
            State("x-align-value", "value"),
            State("show-resultant", "value"),
        ],
    )
    def update_channel_values_style(
        selected_keys: list[str] | None,
        cfc_value: str,
        y_align: bool,
        x_align_method: str,
        x_align_value: float | None,
        show_resultant: bool,
    ) -> list[dict]:
        if not selected_keys:
            return []

        channels = _resolve_channels(
            selected_keys,
            app_state,
            cfc_value,
            y_align,
            x_align_method or "none",
            x_align_value,
            show_resultant,
        )

        style_cond: list[dict] = []
        for i in range(len(channels)):
            color = DEFAULT_COLORS[i % len(DEFAULT_COLORS)]
            style_cond.append(
                {
                    "if": {"row_index": i},
                    "backgroundColor": f"{color}18",
                    "borderLeft": f"3px solid {color}",
                }
            )

        # Highlight cursor column
        style_cond.append(
            {
                "if": {"column_id": "cursor"},
                "color": "#0d6efd",
                "fontWeight": "500",
            }
        )

        return style_cond
