# (c) cavaliba.com - tests / telemetry - seed instrumentation: login signals, federated
# session, active users, api.request, celery task.duration, log2.timed hook

from django.contrib.auth.models import User as DjangoUser
from django.test import TestCase, override_settings
from django.urls import reverse

import app_data.telemetry as T
import app_home.cache as cache
from app_data.models import DataTelemetryRaw, DataTelemetryUnique
from app_data.tasks import task_telemetry_aggregate
from app_home.log import log2
from tests import helper


def _raws(key):
    return list(
        DataTelemetryRaw.objects.filter(key=key).values_list("distinct_id", "type", "value")
    )


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

    @override_settings(CAVALIBA_AUTH_MODE="local")
    def test_local_login_signals(self):
        DjangoUser.objects.create_user("bob", password="pw-123-xyz")
        self.client.post(reverse("login"), {"username": "bob", "password": "wrong"})
        self.client.post(reverse("login"), {"username": "bob", "password": "pw-123-xyz"})
        self.assertEqual(_raws("auth.login.failure"), [("local", "counter", 1)])
        self.assertEqual(_raws("auth.login"), [("local", "counter", 1)])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_federated_session_and_active_user(self):
        helper.add_admin_user(login="unittest")
        self.client.get(reverse("telemetry:index"))
        self.client.get(reverse("telemetry:index"))
        self.assertEqual(_raws("auth.login"), [("unittest", "counter", 1)])
        self.assertEqual(DataTelemetryUnique.objects.filter(key="users.active").count(), 3)

    def test_api_request_counted_with_endpoint(self):
        headers = helper.add_apikey(keyname="tlm_r", acl="p_telemetry_read")
        self.client.get(reverse("api:api_telemetry"), headers=headers)
        self.client.get(reverse("api:api_telemetry"))
        self.assertEqual(_raws("api.request"), [("telemetry", "counter", 1)] * 2)

    def test_log2_timed_feeds_timer(self):
        with log2.timed("eav.refresh"):
            pass
        with self.assertRaises(ValueError), log2.timed("eav.purge"):
            raise ValueError("boom")
        self.assertEqual([r[1] for r in _raws("timed.eav.refresh")], ["timer"])
        self.assertEqual([r[1] for r in _raws("timed.eav.purge")], ["timer"])

    def test_celery_task_duration(self):
        task_telemetry_aggregate.apply()
        raws = _raws("task.duration")
        self.assertEqual([(r[0], r[1]) for r in raws], [("task_telemetry_aggregate", "timer")])
        self.assertGreaterEqual(raws[0][2], 0)
