from datetime import date, datetime, time

from src.core.scheduler import ThrottledSchedulerConfigurator


# #region test_throttled_scheduler [TYPE Module] [C:3] [SEMANTICS test, scheduler, throttle, unit]
# @RELATION BINDS_TO -> SrcRoot
# @BRIEF Unit tests for ThrottledSchedulerConfigurator distribution logic.
# #region test_calculate_schedule_even_distribution [TYPE Function]
# @RELATION BINDS_TO -> [test_throttled_scheduler]
# @BRIEF Validate even spacing across a two-hour scheduling window for three tasks.
def test_calculate_schedule_even_distribution():
    """
    @TEST_SCENARIO: 3 tasks in a 2-hour window should be spaced 1 hour apart.
    """
    start = time(1, 0)
    end = time(3, 0)
    dashboards = ["d1", "d2", "d3"]
    today = date(2024, 1, 1)
    schedule = ThrottledSchedulerConfigurator.calculate_schedule(
        start, end, dashboards, today
    )
    assert len(schedule) == 3
    assert schedule[0] == datetime(2024, 1, 1, 1, 0)
    assert schedule[1] == datetime(2024, 1, 1, 2, 0)
    assert schedule[2] == datetime(2024, 1, 1, 3, 0)
# #endregion test_calculate_schedule_even_distribution
# #region test_calculate_schedule_midnight_crossing [TYPE Function]
# @RELATION BINDS_TO -> [test_throttled_scheduler]
# @BRIEF Validate scheduler correctly rolls timestamps into the next day across midnight.
def test_calculate_schedule_midnight_crossing():
    """
    @TEST_SCENARIO: Window from 23:00 to 01:00 (next day).
    """
    start = time(23, 0)
    end = time(1, 0)
    dashboards = ["d1", "d2", "d3"]
    today = date(2024, 1, 1)
    schedule = ThrottledSchedulerConfigurator.calculate_schedule(
        start, end, dashboards, today
    )
    assert len(schedule) == 3
    assert schedule[0] == datetime(2024, 1, 1, 23, 0)
    assert schedule[1] == datetime(2024, 1, 2, 0, 0)
    assert schedule[2] == datetime(2024, 1, 2, 1, 0)
# #endregion test_calculate_schedule_midnight_crossing
# #region test_calculate_schedule_single_task [TYPE Function]
# @RELATION BINDS_TO -> [test_throttled_scheduler]
# @BRIEF Validate single-task schedule returns only the window start timestamp.
def test_calculate_schedule_single_task():
    """
    @TEST_SCENARIO: Single task should be scheduled at start time.
    """
    start = time(1, 0)
    end = time(2, 0)
    dashboards = ["d1"]
    today = date(2024, 1, 1)
    schedule = ThrottledSchedulerConfigurator.calculate_schedule(
        start, end, dashboards, today
    )
    assert len(schedule) == 1
    assert schedule[0] == datetime(2024, 1, 1, 1, 0)
# #endregion test_calculate_schedule_single_task
# #region test_calculate_schedule_empty_list [TYPE Function]
# @RELATION BINDS_TO -> [test_throttled_scheduler]
# @BRIEF Validate empty dashboard list produces an empty schedule.
def test_calculate_schedule_empty_list():
    """
    @TEST_SCENARIO: Empty dashboard list returns empty schedule.
    """
    start = time(1, 0)
    end = time(2, 0)
    dashboards = []
    today = date(2024, 1, 1)
    schedule = ThrottledSchedulerConfigurator.calculate_schedule(
        start, end, dashboards, today
    )
    assert schedule == []
# #endregion test_calculate_schedule_empty_list
# #region test_calculate_schedule_zero_window [TYPE Function]
# @RELATION BINDS_TO -> [test_throttled_scheduler]
# @BRIEF Validate zero-length window schedules all tasks at identical start timestamp.
def test_calculate_schedule_zero_window():
    """
    @TEST_SCENARIO: Window start == end. All tasks at start time.
    """
    start = time(1, 0)
    end = time(1, 0)
    dashboards = ["d1", "d2"]
    today = date(2024, 1, 1)
    schedule = ThrottledSchedulerConfigurator.calculate_schedule(
        start, end, dashboards, today
    )
    assert len(schedule) == 2
    assert schedule[0] == datetime(2024, 1, 1, 1, 0)
    assert schedule[1] == datetime(2024, 1, 1, 1, 0)
# #endregion test_calculate_schedule_zero_window
# #region test_calculate_schedule_very_small_window [TYPE Function]
# @RELATION BINDS_TO -> [test_throttled_scheduler]
# @BRIEF Validate sub-second interpolation when task count exceeds near-zero window granularity.
def test_calculate_schedule_very_small_window():
    """
    @TEST_SCENARIO: Window smaller than number of tasks (in seconds).
    """
    start = time(1, 0, 0)
    end = time(1, 0, 1)  # 1 second window
    dashboards = ["d1", "d2", "d3"]
    today = date(2024, 1, 1)
    schedule = ThrottledSchedulerConfigurator.calculate_schedule(
        start, end, dashboards, today
    )
    assert len(schedule) == 3
    assert schedule[0] == datetime(2024, 1, 1, 1, 0, 0)
    assert schedule[1] == datetime(2024, 1, 1, 1, 0, 0, 500000)  # 0.5s
    assert schedule[2] == datetime(2024, 1, 1, 1, 0, 1)
# #endregion test_calculate_schedule_very_small_window
# #endregion test_throttled_scheduler
