# (c) cavaliba.com - tests / log2 - log browser filters (event_filter_params, event_queryset)

from datetime import timedelta

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

from app_home.log import event_filter_params, event_queryset, log2
from app_home.models import CavalibaEvent


class TestLog2Filter(TestCase):
    def setUp(self):
        CavalibaEvent.objects.all().delete()
        log2.reset(channel="web", actor="alice", request_id="req-a")
        log2.access("instance.detail", target=("server", "web01"))
        log2.ok("instance.update", target=("server", "web01"), message="renamed host")
        log2.reset(channel="api", actor="API:ops", request_id="req-b")
        log2.fail("load.run", reason="partial", target=("site", "paris"))
        log2.reset(channel="web", actor="admin", actor_effective="bob", request_id="req-c")
        log2.deny("task.stop", reason="not_owner", target=("task", "h1"))

    def _actions(self, **query):
        return sorted(event_queryset(event_filter_params(query)).values_list("action", flat=True))

    def test_params_drop_invalid_values(self):
        params = event_filter_params({"level": "loud", "outcome": "maybe", "channel": "x",
                                      "q": " text ", "actor": "a" * 999})  # fmt: skip
        self.assertEqual(params["q"], "text")
        self.assertEqual(len(params["actor"]), 256)
        self.assertNotIn("level", params)
        self.assertNotIn("outcome", params)
        self.assertNotIn("channel", params)

    def test_minimum_level(self):
        self.assertEqual(self._actions(level="WARNING"), ["load.run", "task.stop"])

    def test_outcome_and_channel(self):
        self.assertEqual(self._actions(outcome="denied"), ["task.stop"])
        self.assertEqual(self._actions(channel="api"), ["load.run"])

    def test_action_prefix(self):
        self.assertEqual(self._actions(action="instance."), ["instance.detail", "instance.update"])

    def test_actor_matches_effective_actor(self):
        self.assertEqual(self._actions(actor="bob"), ["task.stop"])

    def test_target_type_and_id(self):
        self.assertEqual(
            self._actions(target="server:web01"), ["instance.detail", "instance.update"]
        )
        self.assertEqual(self._actions(target="site:"), ["load.run"])
        self.assertEqual(self._actions(target="h1"), ["task.stop"])

    def test_request_id(self):
        self.assertEqual(self._actions(request_id="req-a"), ["instance.detail", "instance.update"])

    def test_free_text_on_message_target_reason(self):
        self.assertEqual(self._actions(q="renamed"), ["instance.update"])
        self.assertEqual(self._actions(q="paris"), ["load.run"])
        self.assertEqual(self._actions(q="not_owner"), ["task.stop"])

    def test_date_range(self):
        CavalibaEvent.objects.filter(action="load.run").update(
            created=timezone.now() - timedelta(days=10)
        )
        today = timezone.localdate().isoformat()
        old = (timezone.localdate() - timedelta(days=10)).isoformat()
        self.assertNotIn("load.run", self._actions(since=today))
        self.assertEqual(self._actions(since=old, until=old), ["load.run"])
        self.assertEqual(len(self._actions(since="not-a-date")), 4)
