# (c) cavaliba.com - tests / telemetry - day / week / month rollups from hour aggregates

from datetime import timedelta

from django.test import TestCase

import app_data.telemetry as T
import app_home.cache as cache
from app_data.models import DataTelemetryAggregate
from tests.helper import TELEMETRY_T0, add_telemetry_raw


def _agg(key, period):
    return DataTelemetryAggregate.objects.get(key=key, period=period, distinct_id="")


class TelemetryRollupTest(TestCase):
    def setUp(self):
        cache.clear()
        T.reset_cache()

    def _run_until(self, end, step=timedelta(minutes=30)):
        now = TELEMETRY_T0
        while now < end:
            now += step
            T.telemetry_aggregate(now=now)

    def test_day_rollup_sums_hours(self):
        add_telemetry_raw(TELEMETRY_T0, "x.c", value=2)
        add_telemetry_raw(TELEMETRY_T0 + timedelta(hours=1), "x.c", value=3)

        self._run_until(TELEMETRY_T0 + timedelta(hours=3))

        day = _agg("x.c", "day")
        self.assertEqual((day.count, day.sum, day.min, day.max, day.last), (2, 5, 2, 3, 3))
        self.assertEqual(day.start, T.bucket_start(TELEMETRY_T0, "day"))

    def test_day_not_rolled_before_it_closes(self):
        add_telemetry_raw(TELEMETRY_T0, "x.c")

        self._run_until(TELEMETRY_T0 + timedelta(hours=1, minutes=30))

        self.assertTrue(DataTelemetryAggregate.objects.filter(period="hour").exists())
        self.assertFalse(DataTelemetryAggregate.objects.filter(period="day").exists())

    def test_timer_percentiles_weighted_and_approx(self):
        for _ in range(3):
            add_telemetry_raw(TELEMETRY_T0, "x.t", "timer", 10)
        add_telemetry_raw(TELEMETRY_T0 + timedelta(hours=1), "x.t", "timer", 50)

        self._run_until(TELEMETRY_T0 + timedelta(hours=3))

        day = _agg("x.t", "day")
        self.assertEqual((day.count, day.p95, day.mean), (4, 20, 20))
        self.assertTrue(day.approx)

    def test_set_breakdown_merged(self):
        add_telemetry_raw(TELEMETRY_T0, "x.s", "set", svalue="ok")
        add_telemetry_raw(TELEMETRY_T0 + timedelta(hours=1), "x.s", "set", svalue="ko")
        add_telemetry_raw(TELEMETRY_T0 + timedelta(hours=1), "x.s", "set", svalue="ok")

        self._run_until(TELEMETRY_T0 + timedelta(hours=3))

        day = _agg("x.s", "day")
        self.assertEqual((day.data, day.distinct), ({"ok": 2, "ko": 1}, 2))

    def test_week_and_month_rollup(self):
        add_telemetry_raw(TELEMETRY_T0, "x.c", value=4)
        self._run_until(TELEMETRY_T0 + timedelta(hours=3))

        T.telemetry_aggregate(now=TELEMETRY_T0 + timedelta(days=9))

        self.assertEqual(_agg("x.c", "week").sum, 4)
        self.assertEqual(_agg("x.c", "month").sum, 4)
        self.assertFalse(DataTelemetryAggregate.objects.filter(period="quarter").exists())
