"""Outils de moyennage saisonnier/mensuel et de profils horaires."""

from __future__ import annotations

from typing import Sequence

import pandas as pd

from meteo.season import SEASON_LABELS

from .core import MONTH_ORDER, _ensure_datetime_index, _infer_time_step

__all__ = ['compute_monthly_climatology', 'compute_monthly_means', 'compute_seasonal_hourly_profile', 'compute_monthly_daylight_hours']


def compute_monthly_climatology(
    df: pd.DataFrame,
    *,
    columns: Sequence[str],
) -> pd.DataFrame:
    """
    Moyenne par mois (1–12) pour les colonnes fournies.
    """
    _ensure_datetime_index(df)
    missing = [col for col in columns if col not in df.columns]
    if missing:
        raise KeyError(f"Colonnes absentes : {missing}")

    grouped = df[list(columns)].groupby(df.index.month).mean()
    grouped = grouped.reindex(MONTH_ORDER)
    grouped.index.name = "month"
    return grouped

def compute_monthly_means(
    df: pd.DataFrame,
    *,
    columns: Sequence[str],
) -> pd.DataFrame:
    """
    Moyennes calendaire par mois (indexé sur la fin de mois).
    """
    _ensure_datetime_index(df)
    missing = [col for col in columns if col not in df.columns]
    if missing:
        raise KeyError(f"Colonnes absentes : {missing}")

    monthly = df[list(columns)].resample("1ME").mean()
    return monthly.dropna(how="all")

def compute_seasonal_hourly_profile(
    df: pd.DataFrame,
    *,
    value_column: str,
    season_column: str = "season",
) -> pd.DataFrame:
    """
    Retourne une matrice (heures x saisons) contenant la moyenne d'une variable.
    """
    _ensure_datetime_index(df)
    for col in (value_column, season_column):
        if col not in df.columns:
            raise KeyError(f"Colonne absente : {col}")

    subset = df[[value_column, season_column]].dropna()
    if subset.empty:
        return pd.DataFrame(index=range(24))

    grouped = subset.groupby([season_column, subset.index.hour])[value_column].mean()
    pivot = grouped.unstack(season_column)
    pivot = pivot.reindex(index=range(24))
    order = [season for season in SEASON_LABELS if season in pivot.columns]
    if order:
        pivot = pivot[order]
    pivot.index.name = "hour"
    return pivot

def compute_monthly_daylight_hours(
    df: pd.DataFrame,
    *,
    illuminance_column: str = "illuminance",
    threshold_lux: float = 1000.0,
) -> pd.Series:
    """
    Calcule la durée moyenne de luminosité (> threshold_lux) par mois (en heures par jour).
    """
    _ensure_datetime_index(df)
    if illuminance_column not in df.columns:
        raise KeyError(f"Colonne absente : {illuminance_column}")

    subset = df[[illuminance_column]].dropna()
    if subset.empty:
        return pd.Series(dtype=float)

    time_step = _infer_time_step(subset.index)
    hours_per_step = time_step.total_seconds() / 3600.0

    daylight_flag = (subset[illuminance_column] >= threshold_lux).astype(float)
    daylight_hours = daylight_flag * hours_per_step

    daily_hours = daylight_hours.resample("1D").sum()
    monthly_avg = daily_hours.resample("1ME").mean()
    return monthly_avg.dropna()
