# (c) cavaliba.com - tests / app_data.ipam.get_subnet_hierarchy

from django.test import TestCase

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


class IpamSubnetHierarchyHookTest(TestCase):
    def setUp(self):
        cache.clear()
        # TEST-NET-3 (RFC 5737) - guaranteed not to overlap the builtin
        # 10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12 seeds (220-ipam.yml)
        helper.add_instance(
            classname="ipam_subnet",
            keyname="203.0.113.0/24",
            fields={"description": "grandparent"},
        )
        helper.add_instance(
            classname="ipam_subnet",
            keyname="203.0.113.0/26",
            fields={"description": "target's parent"},
        )
        helper.add_instance(
            classname="ipam_vlan",
            keyname="vlan_grandparent",
            fields={"displayname": "Grandparent VLAN", "subnet": "203.0.113.0/24"},
        )
        helper.add_instance(
            classname="ipam_vlan",
            keyname="vlan_target",
            fields={"displayname": "Target VLAN", "subnet": "203.0.113.0/26"},
        )
        helper.add_instance(classname="ipam_ip", fields={"displayname": "203.0.113.10"})

    def _target(self):
        return Instance.from_keyname(classname="ipam_subnet", keyname="203.0.113.0/26")

    def test_includes_self_and_ancestors_broadest_first(self):
        hierarchy = get_subnet_hierarchy(self._target())

        self.assertEqual(
            [h["keyname"] for h in hierarchy],
            ["0.0.0.0/0", "203.0.113.0/24", "203.0.113.0/26"],
        )
        self.assertEqual([h["is_containing"] for h in hierarchy], [False, False, True])

    def test_vlan_shown_for_every_level_not_just_target(self):
        """Differs from get_ip_subnet_hierarchy(): every row is a real
        curated subnet, so every row gets its own VLAN, not just the
        innermost."""
        hierarchy = get_subnet_hierarchy(self._target())

        by_keyname = {h["keyname"]: h for h in hierarchy}
        self.assertEqual(
            by_keyname["203.0.113.0/24"]["vlans"][0]["displayname"], "Grandparent VLAN"
        )
        self.assertEqual(by_keyname["203.0.113.0/26"]["vlans"][0]["displayname"], "Target VLAN")
        self.assertEqual(by_keyname["0.0.0.0/0"]["vlans"], [])

    def test_subnet_detail_fields_present(self):
        hierarchy = get_subnet_hierarchy(self._target())
        target = next(h for h in hierarchy if h["keyname"] == "203.0.113.0/26")

        self.assertEqual(target["first_ip"], "203.0.113.0")
        self.assertEqual(target["last_ip"], "203.0.113.63")
        self.assertEqual(target["prefixlen"], 26)
        self.assertEqual(target["netmask"], "255.255.255.192")
        self.assertEqual(target["size"], 64)

    def test_occupancy_reflects_ipam_ip_count(self):
        hierarchy = get_subnet_hierarchy(self._target())
        target = next(h for h in hierarchy if h["keyname"] == "203.0.113.0/26")

        self.assertEqual(target["occupancy"]["count"], 1)

    def test_description_populated(self):
        hierarchy = get_subnet_hierarchy(self._target())
        by_keyname = {h["keyname"]: h for h in hierarchy}
        self.assertEqual(by_keyname["203.0.113.0/24"]["description"], "grandparent")
        self.assertEqual(by_keyname["203.0.113.0/26"]["description"], "target's parent")

    def test_invalid_keyname_returns_empty(self):
        instance = Instance(classname="ipam_subnet")
        instance.keyname = "not-a-cidr"
        self.assertEqual(get_subnet_hierarchy(instance), [])
