import unittest
from datetime import date, datetime

import schedule

TODAY = date(2026, 8, 2)
YESTERDAY = date(2026, 8, 1)


def at(hour, minute=0):
    return datetime(2026, 8, 2, hour, minute)


class DecideTests(unittest.TestCase):
    def test_sends_when_yesterday_is_in_the_data(self):
        send, _ = schedule.decide(freshness=YESTERDAY, today=TODAY, now=at(6, 50),
                                  last_sent=None)
        self.assertTrue(send)

    def test_waits_in_the_morning_while_data_is_stale(self):
        """Мак синкает Apple Health, когда проснулся. В 06:50 вчерашнего дня может ещё не быть."""
        send, reason = schedule.decide(freshness=date(2026, 7, 31), today=TODAY,
                                       now=at(6, 50), last_sent=None)
        self.assertFalse(send)
        self.assertIn("ждём", reason)

    def test_sends_anyway_after_the_deadline(self):
        """Правило 4: ежедневный никогда не молчит — после полудня шлём что есть."""
        send, _ = schedule.decide(freshness=date(2026, 7, 31), today=TODAY,
                                  now=at(12, 0), last_sent=None)
        self.assertTrue(send)

    def test_does_not_send_twice_in_one_day(self):
        send, reason = schedule.decide(freshness=YESTERDAY, today=TODAY, now=at(9, 10),
                                       last_sent=TODAY)
        self.assertFalse(send)
        self.assertIn("уже", reason)

    def test_yesterdays_send_does_not_block_today(self):
        send, _ = schedule.decide(freshness=YESTERDAY, today=TODAY, now=at(6, 50),
                                  last_sent=date(2026, 8, 1))
        self.assertTrue(send)

    def test_missing_freshness_still_sends_after_the_deadline(self):
        """Файла нет или шапка не разобралась — молчать всё равно нельзя."""
        send, _ = schedule.decide(freshness=None, today=TODAY, now=at(13, 0), last_sent=None)
        self.assertTrue(send)
        send, _ = schedule.decide(freshness=None, today=TODAY, now=at(7, 0), last_sent=None)
        self.assertFalse(send)

    def test_data_ahead_of_yesterday_counts_as_fresh(self):
        """Синк успел затянуть и сегодняшний день — это тем более свежо."""
        send, _ = schedule.decide(freshness=TODAY, today=TODAY, now=at(6, 50), last_sent=None)
        self.assertTrue(send)


class StateTests(unittest.TestCase):
    def test_roundtrip(self):
        import tempfile
        import pathlib

        with tempfile.TemporaryDirectory() as tmp:
            path = pathlib.Path(tmp) / "state" / "sent.json"
            self.assertIsNone(schedule.load_last_sent(path))
            schedule.save_last_sent(path, TODAY)
            self.assertEqual(schedule.load_last_sent(path), TODAY)

    def test_broken_state_is_not_fatal(self):
        """Битый state не должен отменять утренний пуш — просто считаем, что не слали."""
        import tempfile
        import pathlib

        with tempfile.TemporaryDirectory() as tmp:
            path = pathlib.Path(tmp) / "sent.json"
            path.write_text("не json", encoding="utf-8")
            self.assertIsNone(schedule.load_last_sent(path))


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