from datetime import date

import pytest

from ccma.domain.dates import (
    DateValidationError,
    age_label,
    calculate_age,
    format_date_for_display,
    format_month_for_display,
    normalize_date_input,
    parse_date_input,
    parse_iso_date,
    parse_month_input,
    validate_birth_date,
    validate_member_dates,
)


def test_iso_dates_are_strict_and_real() -> None:
    assert parse_iso_date("2024-02-29", "Datum") == date(2024, 2, 29)
    for value in ("29.02.2024", "2024-2-29", "2023-02-29", "irgendwas"):
        with pytest.raises(DateValidationError):
            parse_iso_date(value, "Datum")


def test_date_input_accepts_german_and_iso_formats() -> None:
    expected = date(2024, 2, 29)
    assert parse_date_input("29.02.2024", "Datum") == expected
    assert parse_date_input("2024-02-29", "Datum") == expected
    assert normalize_date_input("29.02.2024", "Datum") == "2024-02-29"


def test_date_display_uses_system_pattern(monkeypatch) -> None:
    monkeypatch.setattr("ccma.domain.dates.system_date_pattern", lambda: "%d.%m.%Y")
    assert format_date_for_display("2024-02-29") == "29.02.2024"
    monkeypatch.setattr("ccma.domain.dates.system_date_pattern", lambda: "%Y-%m-%d")
    assert format_date_for_display("2024-02-29") == "2024-02-29"


def test_invalid_date_remains_visible_for_correction() -> None:
    assert format_date_for_display("31/12/2000") == "31/12/2000"


def test_birth_date_checks_future_and_plausibility() -> None:
    today = date(2026, 6, 21)
    assert validate_birth_date("2000-06-22", today=today) == date(2000, 6, 22)
    with pytest.raises(DateValidationError, match="Zukunft"):
        validate_birth_date("2026-06-22", today=today)
    with pytest.raises(DateValidationError, match="120"):
        validate_birth_date("1900-01-01", today=today)


def test_member_dates_must_be_chronological() -> None:
    with pytest.raises(DateValidationError, match="Aufnahmebeschluss"):
        validate_member_dates(
            birth_date="2000-01-01",
            accepted_at="2020-01-02",
            membership_started_at="2020-01-01",
            today=date(2026, 6, 21),
        )

    with pytest.raises(DateValidationError, match="Austrittsdatum"):
        validate_member_dates(
            birth_date="2000-01-01",
            accepted_at="2020-01-01",
            membership_started_at="2020-02-01",
            membership_ended_at="2020-01-31",
            today=date(2026, 6, 21),
        )


def test_month_input_accepts_german_and_iso_formats() -> None:
    assert parse_month_input("03.2026", "Ab") == "2026-03"
    assert parse_month_input("2026-03", "Ab") == "2026-03"
    assert parse_month_input("", "Ab") == ""
    with pytest.raises(DateValidationError, match="erforderlich"):
        parse_month_input("", "Ab", allow_empty=False)
    with pytest.raises(DateValidationError):
        parse_month_input("13.2026", "Ab")
    with pytest.raises(DateValidationError):
        parse_month_input("2026-03-15", "Ab")


def test_month_display_uses_system_pattern(monkeypatch) -> None:
    monkeypatch.setattr("ccma.domain.dates.system_date_pattern", lambda: "%d.%m.%Y")
    assert format_month_for_display("2026-03") == "03.2026"
    monkeypatch.setattr("ccma.domain.dates.system_date_pattern", lambda: "%Y-%m-%d")
    assert format_month_for_display("2026-03") == "2026-03"


def test_age_calculation_and_label() -> None:
    today = date(2026, 6, 21)
    assert calculate_age(date(2000, 6, 21), today) == 26
    assert calculate_age(date(2000, 6, 22), today) == 25
    assert age_label("2000-06-21", today=today) == "Alter: 26 Jahre"
    assert age_label("nein", today=today) == "UNGÜLTIGES DATUM"
