"""Unit tests for the ERA5 seed's hourly→daily transform (hermetic — no network, no
icechunk/xarray). The S3 access layer (_open_store/fetch_point) is deliberately not
tested here; it must be verified with `seed_era5.py --dry-run` on the seed box."""
import datetime
import math

import polars as pl
import pytest

import seed_era5

_MS_TO_MPH = 2.2369362920544
_M_TO_IN = 39.37007874


def _rh(t_c, td_c):
    es = math.exp(17.625 * t_c / (243.04 + t_c))
    e = math.exp(17.625 * td_c / (243.04 + td_c))
    return min(100.0, 100.0 * e / es)


def _hourly(rows):
    """rows: list of (time, t2m_K, d2m_K, tp_m, u10, v10, i10fg)."""
    cols = ["time", "t2m", "d2m", "tp", "u10", "v10", "i10fg"]
    return pl.DataFrame({c: [r[i] for r in rows] for i, c in enumerate(cols)})


def test_hourly_to_daily_aggregates_and_converts():
    d1 = datetime.datetime(2020, 1, 1)
    d2 = datetime.datetime(2020, 1, 2)
    hourly = _hourly([
        # day 1: 10°C sat, then 20°C / 10°C dew; winds 5 m/s then calm; gusts 10/12
        (d1.replace(hour=0), 283.15, 283.15, 0.001, 3.0, 4.0, 10.0),
        (d1.replace(hour=1), 293.15, 283.15, 0.002, 0.0, 0.0, 12.0),
        # day 2: 0°C sat; wind 10 m/s; gust 20
        (d2.replace(hour=0), 273.15, 273.15, 0.0, 6.0, 8.0, 20.0),
    ])
    daily = seed_era5.hourly_to_daily(hourly).sort("date")
    assert daily["date"].to_list() == [datetime.date(2020, 1, 1), datetime.date(2020, 1, 2)]

    r0 = daily.row(0, named=True)
    assert r0["tmax"] == pytest.approx(68.0)      # 20°C
    assert r0["tmin"] == pytest.approx(50.0)      # 10°C
    assert r0["precip"] == pytest.approx(0.003 * _M_TO_IN)
    assert r0["wind"] == pytest.approx(5.0 * _MS_TO_MPH)     # max(5, 0)
    assert r0["gust"] == pytest.approx(12.0 * _MS_TO_MPH)    # max(10, 12)
    assert r0["humid"] == pytest.approx((_rh(10, 10) + _rh(20, 10)) / 2)

    r1 = daily.row(1, named=True)
    assert r1["tmin"] == pytest.approx(32.0)      # 0°C
    assert r1["wind"] == pytest.approx(10.0 * _MS_TO_MPH)    # sqrt(6²+8²)


def test_saturated_air_reads_full_humidity():
    hourly = _hourly([(datetime.datetime(2021, 6, 1), 293.15, 293.15, 0.0, 1.0, 1.0, 2.0)])
    daily = seed_era5.hourly_to_daily(hourly)
    assert daily.row(0, named=True)["humid"] == pytest.approx(100.0)


def test_finalize_produces_the_store_schema():
    """The daily frame, run through climate._finalize_approximated (as seed_cell does),
    yields the persisted columns incl. derived feels."""
    from data import climate
    hourly = _hourly([
        (datetime.datetime(2019, 7, 1, 0), 300.0, 290.0, 0.0, 2.0, 2.0, 5.0),
        (datetime.datetime(2019, 7, 1, 1), 305.0, 291.0, 0.001, 3.0, 1.0, 7.0),
    ])
    frame = climate._finalize_approximated(seed_era5.hourly_to_daily(hourly))
    for col in ("date", "tmax", "tmin", "precip", "wind", "gust", "humid",
                "fmax", "fmin", "feels"):
        assert col in frame.columns
    assert frame.height == 1
