# (c) cavaliba.com - tests / ipam / subnet_view()

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

import app_home.cache as cache
from tests import helper


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

        helper.add_schema(
            classname="ipam_subnet",
            options={"keyname_mode": "edit"},
            field_definition={
                "description": {"dataformat": "string", "displayname": "Description"},
                "subnet": {
                    "dataformat": "ipv4",
                    "dataformat_ext": "subnet strict",
                    "displayname": "Subnet",
                },
            },
        )
        helper.add_schema(
            classname="ipam_vlan",
            field_definition={
                "description": {"dataformat": "string", "displayname": "Description"},
                "vlan_id": {"dataformat": "int", "displayname": "VLAN ID"},
                "subnet": {
                    "dataformat": "schema",
                    "dataformat_ext": "ipam_subnet",
                    "cardinal_max": 0,
                    "displayname": "Subnet",
                },
            },
        )
        helper.add_schema(
            classname="subviewtest",
            field_definition={"ip_address": {"dataformat": "ipv4", "displayname": "IP"}},
        )

        helper.add_instance(
            classname="ipam_subnet",
            keyname="192.0.2.0/28",
            fields={"subnet": "192.0.2.0/28", "description": "test subnet"},
        )
        helper.add_instance(
            classname="ipam_vlan",
            keyname="TESTVLAN",
            fields={"displayname": "Test VLAN", "vlan_id": 10, "subnet": ["192.0.2.0/28"]},
        )
        helper.add_instance(
            classname="subviewtest", keyname="host1", fields={"ip_address": "192.0.2.5"}
        )

    def test_unaligned_subnet_query_still_resolves(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.9/28"})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "192.0.2.0/28")
        self.assertContains(response, "Aligned to subnet boundary")

    def test_subnet_shows_occupancy_and_ip_list(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        self.assertContains(response, "host1")
        self.assertContains(response, "192.0.2.5")

    def test_subnet_shows_vlan_link(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        self.assertContains(response, "?vlan=TESTVLAN")

    def test_page_title_includes_subnet_and_description(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        self.assertContains(response, "IPAM - Subnet - 192.0.2.0/28 - test subnet")

    def test_no_search_bar_on_result_page(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        self.assertNotContains(response, 'name="query"')

    def test_subnet_shows_edit_link(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        self.assertContains(response, "/data/private/instance/edit/")

    def test_shows_detail_button_before_edit_button(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        content = response.content.decode()
        detail_url = "/data/private/instance/detail/"
        edit_url = "/data/private/instance/edit/"
        self.assertIn(detail_url, content)
        self.assertIn(edit_url, content)
        self.assertLess(content.index(detail_url), content.index(edit_url))

    def test_shows_a_custom_field_not_hardcoded_in_the_template(self):
        helper.add_schema_field(
            classname="ipam_subnet",
            fields={"notes": {"dataformat": "string", "displayname": "Notes"}},
        )
        helper.add_instance(
            classname="ipam_subnet",
            action="update",
            keyname="192.0.2.0/28",
            fields={"notes": "custom note about this subnet"},
        )
        cache.clear()
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.2.0/28"})
        self.assertContains(response, "Notes")
        self.assertContains(response, "custom note about this subnet")

    @override_settings(CAVALIBA_IPAM_OCCUPANCY_MINPREFIX=20)
    def test_wide_subnet_shows_gated_message_not_a_crash(self):
        helper.add_instance(
            classname="ipam_subnet",
            keyname="192.0.0.0/16",
            fields={"subnet": "192.0.0.0/16", "description": "wide"},
        )
        cache.clear()
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "192.0.0.0/16"})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "Occupancy not computed")

    def test_invalid_subnet_shows_error(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "not-a-subnet"})
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "valid IPv4 subnet")

    def test_unknown_subnet_offers_create_link_prefilled_with_keyname(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "203.0.113.0/28"})
        self.assertContains(response, "/data/private/schema/new/ipam_subnet?keyname=203.0.113.0/28")


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class SubnetViewCreateLinkPermissionTest(TestCase):
    """CAVALIBA_AUTH_MODE="unittest" always acts as the user literally named "unittest"
    (app_data/aaa.py) - so unlike SubnetViewTest above, this user is limited/non-admin so
    has_create_permission("ipam_subnet") is genuinely false."""

    def setUp(self):
        cache.clear()
        helper.add_user_with_perm(login="unittest", perms=["p_ipam_access", "p_ipam_read"])
        helper.add_schema(
            classname="ipam_subnet",
            options={"keyname_mode": "edit"},
            field_definition={
                "description": {"dataformat": "string", "displayname": "Description"},
                "subnet": {
                    "dataformat": "ipv4",
                    "dataformat_ext": "subnet strict",
                    "displayname": "Subnet",
                },
            },
        )

    def test_create_link_hidden_without_create_permission(self):
        response = self.client.get(reverse("app_ipam:subnet_view"), {"subnet": "203.0.113.0/28"})
        self.assertEqual(response.status_code, 200)
        self.assertNotContains(response, "/data/private/schema/new/ipam_subnet")
