# (c) cavaliba.com - tests / telemetry - unique type (high-cardinality distinct count)

from datetime import timedelta

from django.test import TestCase, override_settings
from django.utils import timezone

import app_data.telemetry as T
import app_home.cache as cache
from app_data.models import DataRegistry, DataTelemetryAggregate, DataTelemetryUnique


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

    def test_member_hashed_one_row_per_period(self):
        self.assertTrue(T.telemetry("users.active", value="alice"))
        rows = DataTelemetryUnique.objects.all()
        self.assertEqual(sorted(r.period for r in rows), ["day", "month", "week"])
        self.assertTrue(all(r.member == T.unique_member("alice") != "alice" for r in rows))
        self.assertEqual(len(rows[0].member), 16)

    def test_member_hash_uses_stable_registry_salt(self):
        member = T.unique_member("alice")
        salt = DataRegistry.objects.get(key=T.SALT_REGISTRY_KEY).value
        self.assertEqual(len(salt), 64)
        T.reset_cache()
        with override_settings(SECRET_KEY="another-secret-key"):
            self.assertEqual(T.unique_member("alice"), member)
        self.assertNotEqual(T.unique_member("bob"), member)

    def test_repeat_member_counted_once(self):
        T.telemetry("users.active", value="alice")
        T.telemetry("users.active", value="alice")
        T.reset_cache()
        T.telemetry("users.active", value="alice")
        T.telemetry("users.active", value="bob")
        self.assertEqual(DataTelemetryUnique.objects.count(), 6)

    def test_empty_value_dropped(self):
        self.assertFalse(T.telemetry("users.active"))
        self.assertFalse(T.telemetry("users.active", value=" "))

    def test_live_value_of_open_bucket(self):
        T.telemetry("users.active", value="alice")
        T.telemetry("users.active", value="bob")
        self.assertEqual(T.get_value("users.active", None, "day")["value"], 2)

    def test_close_writes_distinct_and_drops_members(self):
        T.telemetry("users.active", value="alice")
        T.telemetry("users.active", value="bob")

        self.assertEqual(T._close_unique(timezone.now() + timedelta(days=40)), 3)

        self.assertEqual(DataTelemetryUnique.objects.count(), 0)
        aggs = DataTelemetryAggregate.objects.filter(key="users.active")
        self.assertEqual(sorted(a.period for a in aggs), ["day", "month", "week"])
        self.assertTrue(all(a.type == "unique" and a.distinct == 2 for a in aggs))

    def test_open_bucket_not_closed(self):
        T.telemetry("users.active", value="alice")
        self.assertEqual(T._close_unique(timezone.now()), 0)
        self.assertEqual(DataTelemetryUnique.objects.count(), 3)
