# (c) cavaliba.com - tests / loader - refused/failed rows aggregated by load_broker

from django.test import TestCase

import app_home.cache as cache
from app_data.loader import REFUSED_SAMPLES, load_broker, load_instance
from app_home.log import log2
from app_home.models import CavalibaEvent
from tests import helper

WEAK = {"username": "weak", "perms": []}
ADMIN = {"username": "loaderadmin", "perms": ["p_data_admin"]}


class TestLoaderRefusedAggregation(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_schema(classname="aggtest")
        CavalibaEvent.objects.all().delete()
        log2.reset(channel="api")

    def test_denied_rows_give_one_event(self):
        rows = [
            {"classname": "aggtest", "_action": "create", "keyname": f"r{i}"} for i in range(20)
        ]
        reply = load_broker(rows, aaa=WEAK)
        self.assertEqual(reply["count_ko"], 20)
        event = CavalibaEvent.objects.get(action="load.rows")
        self.assertEqual(
            (event.outcome, event.reason, event.count), ("denied", "permission_denied", 20)
        )
        self.assertEqual(len(event.extra["samples"]), REFUSED_SAMPLES)
        self.assertEqual(event.extra["samples"][0], "create aggtest:r0")

    def test_one_event_per_outcome_and_reason(self):
        rows = [
            {"classname": "aggtest", "_action": "update", "keyname": f"missing{i}"}
            for i in range(3)
        ]
        rows += [{"classname": "aggtest", "_action": "bogus", "keyname": "x"}]
        rows += [{"classname": "aggtest", "_action": "create", "keyname": "good"}]
        load_broker(rows, aaa=ADMIN)
        summary = {(e.reason, e.count) for e in CavalibaEvent.objects.filter(action="load.rows")}
        self.assertEqual(summary, {("not_found", 3), ("unknown_action", 1)})
        self.assertTrue(
            CavalibaEvent.objects.filter(action="instance.create", target_id="good").exists()
        )

    def test_permission_rows_join_the_aggregation(self):
        rows = [
            {"classname": "_permission", "_action": "create", "keyname": f"p_x{i}"}
            for i in range(3)
        ]
        load_broker(rows, aaa=WEAK)
        event = CavalibaEvent.objects.get(action="load.rows")
        self.assertEqual(event.count, 3)
        self.assertEqual(event.extra["samples"][0], "create _permission:p_x0")

    def test_direct_load_instance_logs_the_row(self):
        load_instance(
            datadict={"classname": "aggtest", "_action": "update", "keyname": "nope"}, aaa=ADMIN
        )
        event = CavalibaEvent.objects.get(action="instance.update")
        self.assertEqual(
            (event.outcome, event.reason, event.target_id), ("failure", "not_found", "nope")
        )
        self.assertFalse(CavalibaEvent.objects.filter(action="load.rows").exists())
