import random
import unittest
import unittest.mock
import zoneinfo
from datetime import datetime, time, timedelta
from bot.lib import scheduler


class TestNextPeakTimestamp(unittest.TestCase):
    def test_returns_tz_aware_datetime(self):
        now = datetime(2026, 5, 7, 12, 0, tzinfo=zoneinfo.ZoneInfo("UTC"))
        rng = random.Random(0)
        result = scheduler.next_peak_timestamp(now, rng)
        self.assertIsNotNone(result.tzinfo)

    def test_pacific_window_is_tuesday_9_to_11_local(self):
        now = datetime(2026, 5, 7, 12, 0, tzinfo=zoneinfo.ZoneInfo("UTC"))
        rng = random.Random()
        with unittest.mock.patch.object(rng, "choice", side_effect=lambda seq: seq[0]):
            result = scheduler.next_peak_timestamp(now, rng)
        result_local = result.astimezone(zoneinfo.ZoneInfo("America/Los_Angeles"))
        self.assertEqual(result_local.weekday(), 1)
        self.assertGreaterEqual(result_local.hour, 9)
        self.assertLess(result_local.hour, 11)

    def test_cet_window_is_wednesday_9_to_11_local(self):
        now = datetime(2026, 5, 7, 12, 0, tzinfo=zoneinfo.ZoneInfo("UTC"))
        rng = random.Random()
        with unittest.mock.patch.object(rng, "choice", side_effect=lambda seq: seq[1]):
            result = scheduler.next_peak_timestamp(now, rng)
        result_local = result.astimezone(zoneinfo.ZoneInfo("Europe/Berlin"))
        self.assertEqual(result_local.weekday(), 2)
        self.assertGreaterEqual(result_local.hour, 9)
        self.assertLess(result_local.hour, 11)

    def test_jitter_is_millisecond_precise(self):
        now = datetime(2026, 5, 7, 12, 0, tzinfo=zoneinfo.ZoneInfo("UTC"))
        seen = set()
        for seed in range(20):
            rng = random.Random(seed)
            result = scheduler.next_peak_timestamp(now, rng)
            seen.add(result.microsecond)
        self.assertGreater(len(seen), 5)


if __name__ == "__main__":
    unittest.main()
