from datetime import date

import pytest

from lunar_calendar import DayInfo, build_calendar


def test_build_calendar_rejects_invalid_range() -> None:
    with pytest.raises(ValueError):
        build_calendar(date(2026, 1, 10), date(2026, 1, 1))


def test_build_calendar_returns_expected_day_count() -> None:
    rows = build_calendar(date(2026, 1, 1), date(2026, 1, 3))
    assert len(rows) == 3
    assert rows[0].date == "2026-01-01"
    assert rows[-1].date == "2026-01-03"


def test_dayinfo_fields_are_well_typed() -> None:
    row = build_calendar(date(2026, 1, 1), date(2026, 1, 1))[0]
    assert isinstance(row, DayInfo)
    assert isinstance(row.date, str)
    assert isinstance(row.phase, str)
    assert isinstance(row.illumination, float)
    assert isinstance(row.croissante_decroissante, str)
    assert isinstance(row.montante_descendante, str)
    assert isinstance(row.signe, str)
    assert isinstance(row.type_jour, str)
    assert isinstance(row.soleil_lever, str)
    assert isinstance(row.soleil_coucher, str)
    assert isinstance(row.duree_jour, str)
    assert isinstance(row.lune_lever, str)
    assert isinstance(row.lune_coucher, str)
    assert isinstance(row.duree_presence_lune, str)
    assert isinstance(row.saint_du_jour, str)
    assert isinstance(row.saint_de_glace, bool)
    assert isinstance(row.perigee, bool)
    assert isinstance(row.apogee, bool)
    assert isinstance(row.noeud_lunaire, bool)
    assert isinstance(row.transitions_type_jour, list)
    assert isinstance(row.transitions_montante_descendante, list)


def test_saints_de_glace_are_exposed() -> None:
    rows = build_calendar(date(2026, 5, 11), date(2026, 5, 13))
    assert rows[0].saint_du_jour == "Saint Mamert"
    assert rows[1].saint_du_jour == "Saint Pancrace"
    assert rows[2].saint_du_jour == "Saint Servais"
    assert all(r.saint_de_glace for r in rows)


def test_rise_set_fields_are_present() -> None:
    row = build_calendar(date(2026, 2, 22), date(2026, 2, 22))[0]
    assert row.soleil_lever != ""
    assert row.soleil_coucher != ""
    assert row.duree_jour != ""
    assert row.lune_lever != ""
    assert row.lune_coucher != ""


def test_transition_items_have_expected_shape() -> None:
    row = build_calendar(date(2026, 2, 22), date(2026, 2, 22))[0]
    for item in row.transitions_type_jour + row.transitions_montante_descendante:
        assert set(item.keys()) == {"heure", "avant", "apres"}
