from __future__ import annotations

from datetime import datetime
from zoneinfo import ZoneInfo

from supply_infra.config import InfraSettings
from supply_infra.pipeline.dates import (
    build_date_snapshot,
    deadline_for_trigger,
    next_daily_deadline_china,
    next_schedule_china,
    resolve_biz_dt,
)


def _settings() -> InfraSettings:
    return InfraSettings(
        _env_file=None,
        SCHEDULER_TIMEZONE="Asia/Shanghai",
        SCHEDULER_CRON_HOUR=15,
        SCHEDULER_CRON_MINUTE=0,
    )


def test_date_snapshot_is_frozen_from_biz_dt() -> None:
    assert build_date_snapshot("20260727") == {
        "biz_dt": "20260727",
        "global_tree_partition": "20260726",
        "demand_pool_partition": "20260727",
        "video_decode_partition": "20260726",
    }


def test_resolve_biz_dt_uses_scheduler_timezone() -> None:
    now = datetime(2026, 7, 27, 1, 2, tzinfo=ZoneInfo("Asia/Shanghai"))
    assert resolve_biz_dt(None, settings=_settings(), now=now) == "20260727"


def test_deadline_is_next_scheduler_start() -> None:
    now = datetime(2026, 7, 27, 15, 1, tzinfo=ZoneInfo("Asia/Shanghai"))
    deadline = next_schedule_china(settings=_settings(), now=now)
    assert deadline.isoformat() == "2026-07-28T15:00:00"


def test_scheduled_daily_deadline_is_always_next_local_day() -> None:
    before_cron = datetime(2026, 7, 27, 14, 0, tzinfo=ZoneInfo("Asia/Shanghai"))
    after_cron = datetime(2026, 7, 27, 16, 0, tzinfo=ZoneInfo("Asia/Shanghai"))

    assert next_daily_deadline_china(
        settings=_settings(),
        now=before_cron,
    ).isoformat() == "2026-07-28T15:00:00"
    assert next_daily_deadline_china(
        settings=_settings(),
        now=after_cron,
    ).isoformat() == "2026-07-28T15:00:00"


def test_only_scheduled_triggers_receive_a_deadline() -> None:
    now = datetime(2026, 7, 27, 15, 0, tzinfo=ZoneInfo("Asia/Shanghai"))

    assert deadline_for_trigger(
        "cron",
        settings=_settings(),
        now=now,
    ).isoformat() == "2026-07-28T15:00:00"
    assert deadline_for_trigger(
        "reconcile",
        settings=_settings(),
        now=now,
    ).isoformat() == "2026-07-28T15:00:00"
    assert deadline_for_trigger("api", settings=_settings(), now=now) is None
    assert deadline_for_trigger("cli", settings=_settings(), now=now) is None
