# (c) cavaliba.com - tests / task_manager / timestamp second precision

from django.test import TestCase

from app_data.models import DataTask
from app_data.task_manager import abort_task, create_datatask, finish_task, update_progress

ISO_SECONDS_RE = r"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2}$"


class TestTaskManagerTimestampSecondPrecision(TestCase):
    def test_progress_last_update_has_no_fractional_seconds(self):
        dt = create_datatask("t", owner_id="u1")
        update_progress(dt.handle, percent=50, message="halfway")
        dt.refresh_from_db()
        stamp = dt.progress["last_update"]
        self.assertRegex(stamp, ISO_SECONDS_RE)
        self.assertNotIn(".", stamp)

    def test_finish_task_finished_at_has_no_microseconds(self):
        dt = create_datatask("t", owner_id="u1")
        finish_task(dt.handle, state="DONE")
        dt.refresh_from_db()
        self.assertIsNotNone(dt.finished_at)
        self.assertEqual(dt.finished_at.microsecond, 0)

    def test_finish_task_duration_is_never_negative(self):
        # created_at is auto_now_add (microsecond-exact), so truncating the clock
        # before subtracting it would make a sub-second task look negative
        dt = create_datatask("t", owner_id="u1")
        finish_task(dt.handle, state="DONE")
        dt.refresh_from_db()
        self.assertIsNotNone(dt.duration)
        self.assertGreaterEqual(dt.duration, 0)

    def test_abort_task_finished_at_has_no_microseconds(self):
        dt = create_datatask("t", owner_id="u1")
        self.assertTrue(abort_task(dt.handle))
        dt.refresh_from_db()
        self.assertEqual(dt.state, "ABORTED")
        self.assertIsNotNone(dt.finished_at)
        self.assertEqual(dt.finished_at.microsecond, 0)

    def test_abort_task_duration_is_never_negative(self):
        dt = create_datatask("t", owner_id="u1")
        abort_task(dt.handle)
        dt.refresh_from_db()
        self.assertIsNotNone(dt.duration)
        self.assertGreaterEqual(dt.duration, 0)

    def test_update_progress_duration_is_never_negative(self):
        dt = create_datatask("t", owner_id="u1")
        DataTask.objects.filter(handle=dt.handle).update(state="RUNNING")
        update_progress(dt.handle, percent=10)
        dt.refresh_from_db()
        self.assertIsNotNone(dt.duration)
        self.assertGreaterEqual(dt.duration, 0)
