"""Jeux de paires et scénarios standardisés pour explorer les corrélations."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Callable, Sequence

import numpy as np


HexbinReducer = Callable[[np.ndarray], float]


HEXBIN_REDUCE_FUNCTIONS: dict[str, HexbinReducer] = {
    "mean": np.mean,
    "median": np.median,
    "max": np.max,
}

HEXBIN_REDUCE_LABELS: dict[str, str] = {
    "mean": "moyenne",
    "median": "médiane",
    "max": "maximum",
}

@dataclass(frozen=True)
class CorrelationBand:
    """Intervalle de corrélation, avec couleur et étiquette pour l'affichage."""

    min_value: float
    max_value: float
    label: str
    color: str


# Repères par défaut pour lire rapidement l'intensité (en |r|)
DEFAULT_ABS_CORRELATION_BANDS: Sequence[CorrelationBand] = (
    CorrelationBand(0.0, 0.1, "Quasi nulle", "#f6f6f6"),
    CorrelationBand(0.1, 0.3, "Faible", "#dce8f7"),
    CorrelationBand(0.3, 0.5, "Modérée", "#c8e6c9"),
    CorrelationBand(0.5, 1.0, "Forte", "#ffe0b2"),
)

# Bandes pour corrélations signées (symétriques autour de 0)
DEFAULT_SIGNED_CORRELATION_BANDS: Sequence[CorrelationBand] = (
    CorrelationBand(-1.0, -0.5, "Forte négative", "#c6dbef"),
    CorrelationBand(-0.5, -0.3, "Modérée négative", "#deebf7"),
    CorrelationBand(-0.3, -0.1, "Faible négative", "#edf8fb"),
    CorrelationBand(-0.1, 0.1, "Quasi nulle", "#f5f5f5"),
    CorrelationBand(0.1, 0.3, "Faible positive", "#fff7ec"),
    CorrelationBand(0.3, 0.5, "Modérée positive", "#fee8c8"),
    CorrelationBand(0.5, 1.0, "Forte positive", "#fdbb84"),
)


@dataclass(frozen=True)
class HexbinScenario:
    """Décrit un cas d'usage pour un nuage hexbin coloré par une 3ᵉ variable."""

    key_x: str
    key_y: str
    key_color: str
    filename: str
    description: str
    reduce: str = "mean"
    gridsize: int = 60
    mincnt: int = 5

    def get_reduce_func(self) -> HexbinReducer:
        """Retourne la fonction de réduction associée (moyenne, médiane, ...)."""

        return HEXBIN_REDUCE_FUNCTIONS.get(self.reduce, np.mean)

    def get_reduce_label(self) -> str:
        """Libellé français de la fonction de réduction utilisée."""

        return HEXBIN_REDUCE_LABELS.get(self.reduce, self.reduce)


DEFAULT_LAGGED_PAIRS: Sequence[tuple[str, str]] = (
    ("temperature", "humidity"),
    ("temperature", "rain_rate"),
    ("pressure", "rain_rate"),
    ("pressure", "wind_speed"),
    ("pressure", "illuminance"),
    ("illuminance", "temperature"),
    ("humidity", "rain_rate"),
)


DEFAULT_ROLLING_PAIRS: Sequence[tuple[str, str]] = (
    ("temperature", "humidity"),
    ("pressure", "rain_rate"),
    ("pressure", "wind_speed"),
    ("illuminance", "temperature"),
    ("humidity", "rain_rate"),
)


DEFAULT_HEXBIN_SCENARIOS: Sequence[HexbinScenario] = (
    HexbinScenario(
        key_x="temperature",
        key_y="humidity",
        key_color="rain_rate",
        filename="hexbin_temp_humidity_color_rain.png",
        description=(
            "Mettre en évidence comment l'humidité relative plafonne lorsque la température chute "
            "et comment les épisodes de pluie se situent dans une bande restreinte."
        ),
        reduce="max",
        gridsize=50,
        mincnt=8,
    ),
    HexbinScenario(
        key_x="pressure",
        key_y="rain_rate",
        key_color="wind_speed",
        filename="hexbin_pressure_rain_color_wind.png",
        description=(
            "Vérifier si des rafales accompagnent vraiment les chutes de pression. "
            "On s'attend à voir beaucoup de cases vides : la corrélation est loin d'être systématique."
        ),
        reduce="median",
        gridsize=45,
        mincnt=5,
    ),
    HexbinScenario(
        key_x="illuminance",
        key_y="humidity",
        key_color="temperature",
        filename="hexbin_lux_humidity_color_temp.png",
        description=(
            "Explorer le cycle jour/nuit : l'humidité monte quand l'illuminance chute, "
            "mais cela n'implique pas toujours une baisse rapide de température."
        ),
        reduce="mean",
        gridsize=55,
        mincnt=6,
    ),
)


__all__ = [
    "HexbinScenario",
    "DEFAULT_LAGGED_PAIRS",
    "DEFAULT_ROLLING_PAIRS",
    "DEFAULT_HEXBIN_SCENARIOS",
    "CorrelationBand",
    "DEFAULT_ABS_CORRELATION_BANDS",
    "DEFAULT_SIGNED_CORRELATION_BANDS",
]
