# scripts/plot_calendar_overview.py
from __future__ import annotations

from pathlib import Path

import calendar
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from meteo.dataset import load_raw_csv
from meteo.analysis import compute_daily_rainfall_totals
from meteo.plots import export_plot_dataset, plot_calendar_heatmap, plot_weekday_profiles
from meteo.variables import VARIABLES_BY_KEY


CSV_PATH = Path("data/weather_minutely.csv")
OUTPUT_DIR = Path("figures/calendar")

WEEKDAY_VARIABLE_KEYS = ["temperature", "humidity", "wind_speed", "illuminance"]


def _format_calendar_matrix(series: pd.Series, year: int, agg_label: str) -> pd.DataFrame:
    """
    Transforme une série quotidienne en matrice mois x jours (1-31).
    """
    start = pd.Timestamp(year=year, month=1, day=1, tz=series.index.tz)
    end = pd.Timestamp(year=year, month=12, day=31, tz=series.index.tz)
    filtered = series.loc[(series.index >= start) & (series.index <= end)]

    matrix = pd.DataFrame(
        np.nan,
        index=[calendar.month_name[m][:3] for m in range(1, 13)],
        columns=list(range(1, 32)),
    )

    for timestamp, value in filtered.items():
        month = timestamp.month
        day = timestamp.day
        matrix.at[calendar.month_name[month][:3], day] = value

    matrix.index.name = f"{agg_label} ({year})"
    return matrix


def compute_daily_mean(df: pd.DataFrame, column: str) -> pd.Series:
    return df[column].resample("1D").mean()


def plot_combined_calendar(
    matrices: dict[str, pd.DataFrame],
    output_path: Path,
    *,
    title: str,
) -> None:
    if not matrices:
        return

    combined_dataset = pd.concat(matrices, axis=1)
    export_plot_dataset(combined_dataset, output_path)

    n = len(matrices)
    fig, axes = plt.subplots(n, 1, figsize=(14, 4 * n), sharex=True)
    if n == 1:
        axes = [axes]

    for ax, (label, matrix) in zip(axes, matrices.items()):
        data = matrix.to_numpy(dtype=float)
        im = ax.imshow(data, aspect="auto", interpolation="nearest", cmap=matrix.attrs.get("cmap", "viridis"))
        ax.set_xticks(np.arange(matrix.shape[1]))
        ax.set_xticklabels(matrix.columns, rotation=90)
        ax.set_yticks(np.arange(matrix.shape[0]))
        ax.set_yticklabels(matrix.index)
        ax.set_ylabel(label)
        cbar = fig.colorbar(im, ax=ax)
        if matrix.attrs.get("colorbar_label"):
            cbar.set_label(matrix.attrs["colorbar_label"])

    axes[-1].set_xlabel("Jour du mois")
    fig.suptitle(title)
    fig.tight_layout(rect=[0, 0, 1, 0.97])
    fig.savefig(output_path, dpi=150)
    plt.close(fig)


def main() -> None:
    if not CSV_PATH.exists():
        print(f"⚠ Fichier introuvable : {CSV_PATH}")
        return

    df = load_raw_csv(CSV_PATH)
    if df.empty:
        print("⚠ Dataset vide.")
        return

    if not isinstance(df.index, pd.DatetimeIndex):
        print("⚠ Le dataset doit avoir un index temporel.")
        return

    print(f"Dataset minuté chargé : {CSV_PATH}")
    print(f"  Lignes   : {len(df)}")
    print(f"  Colonnes : {list(df.columns)}")
    print()

    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

    latest_year = df.index.year.max()
    print(f"Année retenue pour le calendrier : {latest_year}")

    daily_totals = compute_daily_rainfall_totals(df=df)
    daily_rain = daily_totals["daily_total"]
    rain_matrix = _format_calendar_matrix(daily_rain, latest_year, "Pluie (mm)")
    rain_matrix.attrs["cmap"] = "Blues"
    rain_matrix.attrs["colorbar_label"] = "mm"
    rain_path = OUTPUT_DIR / f"calendar_rain_{latest_year}.png"
    plot_calendar_heatmap(
        matrix=rain_matrix,
        output_path=rain_path,
        title=f"Pluie quotidienne - {latest_year}",
        cmap="Blues",
        colorbar_label="mm",
    )
    print(f"✔ Heatmap pluie {latest_year} : {rain_path}")

    daily_temp = compute_daily_mean(df, "temperature")
    temp_matrix = _format_calendar_matrix(daily_temp, latest_year, "Température (°C)")
    temp_matrix.attrs["cmap"] = "coolwarm"
    temp_matrix.attrs["colorbar_label"] = "°C"
    temp_path = OUTPUT_DIR / f"calendar_temperature_{latest_year}.png"
    plot_calendar_heatmap(
        matrix=temp_matrix,
        output_path=temp_path,
        title=f"Température moyenne quotidienne - {latest_year}",
        cmap="coolwarm",
        colorbar_label="°C",
    )
    print(f"✔ Heatmap température {latest_year} : {temp_path}")

    matrices_for_combined = {
        "Pluie (mm)": rain_matrix,
        "Température (°C)": temp_matrix,
    }

    if "pressure" in df.columns:
        daily_pressure = compute_daily_mean(df, "pressure")
        pressure_matrix = _format_calendar_matrix(daily_pressure, latest_year, "Pression (hPa)")
        pressure_matrix.attrs["cmap"] = "Greens"
        pressure_matrix.attrs["colorbar_label"] = "hPa"
        pressure_path = OUTPUT_DIR / f"calendar_pressure_{latest_year}.png"
        plot_calendar_heatmap(
            matrix=pressure_matrix,
            output_path=pressure_path,
            title=f"Pression moyenne quotidienne - {latest_year}",
            cmap="Greens",
            colorbar_label="hPa",
        )
        print(f"✔ Heatmap pression {latest_year} : {pressure_path}")
        matrices_for_combined["Pression (hPa)"] = pressure_matrix

    if "illuminance" in df.columns:
        daily_lux = compute_daily_mean(df, "illuminance")
        lux_matrix = _format_calendar_matrix(daily_lux, latest_year, "Illuminance (lux)")
        lux_matrix.attrs["cmap"] = "YlOrBr"
        lux_matrix.attrs["colorbar_label"] = "lux"
        lux_path = OUTPUT_DIR / f"calendar_illuminance_{latest_year}.png"
        plot_calendar_heatmap(
            matrix=lux_matrix,
            output_path=lux_path,
            title=f"Illuminance moyenne quotidienne - {latest_year}",
            cmap="YlOrBr",
            colorbar_label="lux",
        )
        print(f"✔ Heatmap illuminance {latest_year} : {lux_path}")
        matrices_for_combined["Illuminance (lux)"] = lux_matrix

    if "wind_speed" in df.columns:
        daily_wind = compute_daily_mean(df, "wind_speed")
        wind_matrix = _format_calendar_matrix(daily_wind, latest_year, "Vent (km/h)")
        wind_matrix.attrs["cmap"] = "Purples"
        wind_matrix.attrs["colorbar_label"] = "km/h"
        wind_path = OUTPUT_DIR / f"calendar_wind_{latest_year}.png"
        plot_calendar_heatmap(
            matrix=wind_matrix,
            output_path=wind_path,
            title=f"Vitesse moyenne du vent - {latest_year}",
            cmap="Purples",
            colorbar_label="km/h",
        )
        print(f"✔ Heatmap vent {latest_year} : {wind_path}")
        matrices_for_combined["Vent (km/h)"] = wind_matrix

    combined_path = OUTPUT_DIR / f"calendar_combined_{latest_year}.png"
    plot_combined_calendar(
        matrices=matrices_for_combined,
        output_path=combined_path,
        title=f"Calendrier combiné {latest_year}",
    )
    print(f"✔ Calendrier combiné : {combined_path}")

    hourly = df[WEEKDAY_VARIABLE_KEYS].resample("1h").mean()
    weekday_stats = hourly.groupby(hourly.index.dayofweek).mean()
    weekday_path = OUTPUT_DIR / "weekday_profiles.png"
    variables = [VARIABLES_BY_KEY[key] for key in WEEKDAY_VARIABLE_KEYS]
    plot_weekday_profiles(
        weekday_df=weekday_stats,
        variables=variables,
        output_path=weekday_path,
        title="Profils moyens par jour de semaine",
    )
    print(f"✔ Profils hebdomadaires : {weekday_path}")

    print("✔ Graphiques calendrier générés.")


if __name__ == "__main__":
    main()
