"""Corridor management callbacks.

Handles:
- CSV upload -> parse and store corridor data
- Toggle corridor visibility
- Remove corridor
"""

from __future__ import annotations

import base64
import io
from typing import Any

import dash
import numpy as np
from dash import Input, Output, State, html
from dash.exceptions import PreventUpdate

from impakt.web.state import AppState


def register_corridor_callbacks(app: dash.Dash, app_state: AppState) -> None:
    """Register corridor management callbacks."""

    @app.callback(
        [
            Output("corridors-store", "data"),
            Output("corridor-status", "children"),
            Output("active-corridors-list", "children"),
        ],
        [Input("corridor-upload", "contents")],
        [
            State("corridor-upload", "filename"),
            State("corridor-name-input", "value"),
            State("corridors-store", "data"),
        ],
        prevent_initial_call=True,
    )
    def upload_corridor(
        contents: str | None,
        filename: str | None,
        corridor_name: str | None,
        current_corridors: list[dict[str, Any]] | None,
    ) -> tuple[list[dict[str, Any]], Any, list]:
        if contents is None:
            raise PreventUpdate

        # Parse the uploaded CSV
        try:
            content_type, content_string = contents.split(",", 1)
            decoded = base64.b64decode(content_string).decode("utf-8")

            # Parse CSV: expect time, lower, upper columns
            lines = decoded.strip().splitlines()

            # Skip header if present
            data_lines = []
            for line in lines:
                stripped = line.strip()
                if not stripped or stripped.startswith("#"):
                    continue
                # Try to parse first value as float to detect header
                parts = stripped.split(",")
                try:
                    float(parts[0].strip())
                    data_lines.append(stripped)
                except ValueError:
                    continue  # Skip header

            if not data_lines:
                return (
                    current_corridors or [],
                    html.Div("No data found in CSV", className="text-danger small"),
                    _build_corridor_list(current_corridors or []),
                )

            # Parse values
            time_vals = []
            lower_vals = []
            upper_vals = []
            for line in data_lines:
                parts = [p.strip() for p in line.split(",")]
                if len(parts) >= 3:
                    time_vals.append(float(parts[0]))
                    lower_vals.append(float(parts[1]))
                    upper_vals.append(float(parts[2]))

            if not time_vals:
                return (
                    current_corridors or [],
                    html.Div("Could not parse CSV data", className="text-danger small"),
                    _build_corridor_list(current_corridors or []),
                )

            name = corridor_name or (filename or "corridor").rsplit(".", 1)[0]

            corridor = {
                "name": name,
                "time": time_vals,
                "lower": lower_vals,
                "upper": upper_vals,
                "visible": True,
            }

            # Add to state
            app_state.corridors.append(corridor)
            updated = list(current_corridors or []) + [corridor]

            return (
                updated,
                html.Div(
                    f"Loaded '{name}' ({len(time_vals)} points)", className="text-success small"
                ),
                _build_corridor_list(updated),
            )

        except Exception as e:
            return (
                current_corridors or [],
                html.Div(f"Upload failed: {e}", className="text-danger small"),
                _build_corridor_list(current_corridors or []),
            )


def _build_corridor_list(corridors: list[dict[str, Any]]) -> list:
    """Build the active corridors display list."""
    if not corridors:
        return [html.Div("No corridors loaded", className="text-muted", style={"fontSize": "10px"})]

    items = []
    for i, c in enumerate(corridors):
        items.append(
            html.Div(
                [
                    html.Span(
                        c["name"],
                        style={"fontSize": "11px", "fontWeight": "500"},
                    ),
                    html.Span(
                        f" ({len(c['time'])} pts)",
                        style={"fontSize": "10px", "color": "#999"},
                    ),
                ],
                className="mb-1",
            )
        )

    return items
