import datetime as dt

import pytest

from schedint.core.storage import _now_utc, _parse_utc


def test_parse_utc_none_returns_none():
    assert _parse_utc(None) is None


def test_parse_utc_valid_timestamp():
    timestamp = "2026-01-23T12:34:56Z"
    out = _parse_utc(timestamp)

    assert isinstance(out, dt.datetime)
    assert out.tzinfo == dt.timezone.utc
    assert out.year == 2026
    assert out.month == 1
    assert out.day == 23
    assert out.hour == 12
    assert out.minute == 34
    assert out.second == 56


@pytest.mark.parametrize("bad", [123, 12.5, [], {}, object()])
def test_parse_utc_non_string_raises_value_error(bad):
    with pytest.raises(
        ValueError, match=r"Timestamp must be a string or null"
    ):
        _parse_utc(bad)


@pytest.mark.parametrize(
    "bad_ts",
    [
        "2026-13-01T00:00:00Z",  # Month out of range
        "2026-02-30T00:00:00Z",  # Day out of range
        "2026-01-01T24:00:00Z",  # Hour out of range
        "2026-01-01T23:60:00Z",  # Minute out of range
        "2026-01-01T23:59:72Z",  # Second out of range
    ],
)
def test_parse_utc_invalid_date_raises_value_error(bad_ts):
    with pytest.raises(ValueError):
        _parse_utc(bad_ts)


def test_now_utc_returns_datetime():
    now = _now_utc()
    assert isinstance(now, dt.datetime)


def test_now_utc_is_timezone_aware():
    now = _now_utc()
    assert now.tzinfo is not None
    assert now.tzinfo == dt.timezone.utc


def test_now_utc_is_close_to_system_utc_time():
    before = dt.datetime.now(dt.timezone.utc)
    now = _now_utc()
    after = dt.datetime.now(dt.timezone.utc)

    assert before <= now <= after
