# (c) cavaliba.com - tests / instance_list / generic "schema"-type cell click-through
# (app_data/templates/app_data/fields/_schema.html, list display_mode - any
# classname other than ipam_subnet/ipam_vlan, which already linked before this change -
# includes "user"/"group"/"role" fields, normalized to dataformat:schema at schema save time)

from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from app_data.data import Instance
from tests import helper

ADMIN_AAA = {"perms": ["p_data_admin"]}


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class InstanceListSchemaCellLinkTest(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")

        helper.add_schema("cell_target", displayname="Cell Target")
        helper.add_schema(
            "cell_source", displayname="Cell Source",
            field_definition={
                "owner": {
                    "displayname": "Owner",
                    "dataformat": "user",
                    "cardinal_max": 0,
                },
                "ref": {
                    "displayname": "Ref",
                    "dataformat": "schema",
                    "dataformat_ext": "cell_target",
                    "cardinal_max": 0,
                },
            },
        )  # fmt: skip
        helper.add_instance(
            "_dataview", "cell_source_default",
            fields={"target_class": "cell_source", "content": "columns:\n  - owner\n  - ref\n"},
        )  # fmt: skip

        helper.add_instance("cell_target", "target-a", fields={"displayname": "Target A"})
        helper.add_instance("cell_target", "target-b", fields={"displayname": "Target B"})
        # plain "user" instance, NOT add_admin_user() - that overwrites role_admin's
        # whole "users" list (see helper_iam.py), which would kick "unittest" (the
        # login this test's client is authenticated as) back out of role_admin
        helper.add_instance("user", "celluser", fields={"displayname": "Cell User"})

    def _list_response(self):
        return self.client.get(reverse("app_data:instance_list", args=["cell_source"]))

    def test_user_field_cell_links_to_user_detail(self):
        helper.add_instance("cell_source", "src-user", fields={"owner": "celluser"})
        user_instance = Instance.from_keyname(classname="user", keyname="celluser")

        response = self._list_response()

        self.assertEqual(response.status_code, 200)
        self.assertContains(
            response, reverse("app_data:instance_detail", kwargs={"id": user_instance.id})
        )
        self.assertContains(response, "cv-schema-cell-link")

    def test_generic_schema_field_cell_links_in_list(self):
        helper.add_instance("cell_source", "src-ref", fields={"ref": "target-a"})
        target = Instance.from_keyname(classname="cell_target", keyname="target-a")

        response = self._list_response()

        self.assertContains(response, reverse("app_data:instance_detail", kwargs={"id": target.id}))

    def test_multi_valued_schema_field_links_each_value(self):
        helper.add_instance("cell_source", "src-multi", fields={"ref": ["target-a", "target-b"]})
        target_a = Instance.from_keyname(classname="cell_target", keyname="target-a")
        target_b = Instance.from_keyname(classname="cell_target", keyname="target-b")

        response = self._list_response()

        self.assertContains(
            response, reverse("app_data:instance_detail", kwargs={"id": target_a.id})
        )
        self.assertContains(
            response, reverse("app_data:instance_detail", kwargs={"id": target_b.id})
        )

    def test_disabled_referenced_instance_gets_disabled_style(self):
        helper.add_instance("cell_source", "src-disabled", fields={"ref": "target-a"})
        target = Instance.from_keyname(classname="cell_target", keyname="target-a")
        target.disable(aaa=ADMIN_AAA)

        response = self._list_response()

        self.assertContains(response, "cv-instance-disabled")

    def test_dangling_reference_shows_placeholder_without_link(self):
        """A field value pointing at a keyname that no longer exists (e.g. the
        target was deleted directly, bypassing referrer cleanup) must render
        the "?? - keyname" placeholder as plain text, not a link - id=999999999999
        (field_schema.py's sentinel) would 404."""
        helper.add_instance("cell_source", "src-dangling", fields={"ref": "ghost-key"})

        response = self._list_response()

        self.assertContains(response, "?? - ghost-key")
        self.assertNotContains(response, "999999999999")
