# meteo/solar.py
from __future__ import annotations

import pandas as pd
from astral import Observer
from astral.sun import elevation


def _ensure_datetime_index(index: pd.Index) -> pd.DatetimeIndex:
    if not isinstance(index, pd.DatetimeIndex):
        raise TypeError("Un DatetimeIndex est requis pour calculer l'élévation solaire.")
    return index


def _prepare_index(index: pd.DatetimeIndex) -> pd.DatetimeIndex:
    """
    Retourne une version timezone-aware (en UTC) du DatetimeIndex fourni.
    """
    if index.tz is None:
        return index.tz_localize("UTC")
    return index.tz_convert("UTC")


def compute_solar_elevation_series(
    index: pd.Index,
    *,
    latitude: float,
    longitude: float,
    elevation_m: float = 0.0,
    series_name: str = "sun_elevation",
) -> pd.Series:
    """
    Calcule l'élévation du soleil (en degrés) pour chaque timestamp de l'index.
    """
    dt_index = _ensure_datetime_index(index)
    observer = Observer(latitude=latitude, longitude=longitude, elevation=elevation_m)
    utc_index = _prepare_index(dt_index)

    values = [
        float(elevation(observer, ts.to_pydatetime()))
        for ts in utc_index
    ]

    return pd.Series(values, index=dt_index, name=series_name)


def add_solar_elevation_column(
    df: pd.DataFrame,
    *,
    latitude: float,
    longitude: float,
    elevation_m: float = 0.0,
    column_name: str = "sun_elevation",
) -> pd.DataFrame:
    """
    Ajoute une colonne `column_name` contenant l'élévation du soleil en degrés.
    """
    series = compute_solar_elevation_series(
        df.index,
        latitude=latitude,
        longitude=longitude,
        elevation_m=elevation_m,
        series_name=column_name,
    )
    df[column_name] = series
    return df
