# (c) cavaliba.com - test_schema_keyname_mode_dataformat

from django.test import TestCase

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


class TestSchemaKeynameModeDataformatParsing(TestCase):
    def setUp(self):
        """Reset the app-level cache before each test."""
        cache.clear()

    def test_keyname_mode_dataformat_round_trips(self):
        """A well-formed "dataformat <DATAFORMAT> OPT..." string is stored as-is."""
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_mode, "dataformat ipv4 subnet strict")

    def test_keyname_mode_dataformat_unknown_format_falls_back_to_edit(self):
        """An unknown DATAFORMAT token is treated like any other invalid value."""
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat bogus"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_mode, "edit")

    def test_keyname_mode_dataformat_schema_is_not_whitelisted(self):
        """ "schema" is deliberately excluded (FieldSchema.is_valid() has no
        existence check yet)."""
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat schema othertestschema"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_mode, "edit")

    def test_keyname_dataformat_property(self):
        """keyname_dataformat returns the DATAFORMAT token."""
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_dataformat, "ipv4")

    def test_keyname_dataformat_ext_property(self):
        """keyname_dataformat_ext returns everything after DATAFORMAT."""
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_dataformat_ext, "subnet strict")

    def test_keyname_dataformat_ext_property_no_opt(self):
        """keyname_dataformat_ext is "" when no OPT tokens are given."""
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat string"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_dataformat_ext, "")

    def test_keyname_dataformat_property_none_for_edit_mode(self):
        """keyname_dataformat is None for the plain "edit" mode."""
        schema = helper.add_schema(
            classname="unittestschema", options={"keyname_mode": "edit"}, verbose=False
        )
        self.assertIsNone(schema.keyname_dataformat)


class TestSchemaKeynameHelp(TestCase):
    def setUp(self):
        """Reset the app-level cache before each test."""
        cache.clear()

    def test_keyname_help_default_is_empty_string(self):
        schema = helper.add_schema(classname="unittestschema", verbose=False)
        self.assertEqual(schema.keyname_help, "")

    def test_keyname_help_stored_and_returned(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"keyname_help": "CIDR range, e.g. 10.1.2.0/24"},
            verbose=False,
        )
        self.assertEqual(schema.keyname_help, "CIDR range, e.g. 10.1.2.0/24")

    def test_keyname_help_to_dict_includes_when_set(self):
        schema = helper.add_schema(
            classname="unittestschema", options={"keyname_help": "some help"}, verbose=False
        )
        d = schema.to_dict()
        self.assertEqual(d["_options"]["keyname_help"], "some help")

    def test_keyname_help_to_dict_omits_when_empty(self):
        schema = helper.add_schema(classname="unittestschema", verbose=False)
        d = schema.to_dict()
        self.assertNotIn("keyname_help", d["_options"])


class TestInstanceIsValidKeynameDataformat(TestCase):
    def setUp(self):
        """Reset the app-level cache before each test."""
        cache.clear()

    def test_is_valid_accepts_matching_keyname(self):
        helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        instance = Instance(classname="unittestschema", keyname="10.1.2.0/24")
        self.assertTrue(instance.is_valid())

    def test_is_valid_rejects_non_matching_keyname(self):
        helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        instance = Instance(classname="unittestschema", keyname="not-an-ip")
        self.assertFalse(instance.is_valid())
        self.assertIn("invalid keyname format", instance.errors)

    def test_is_valid_ignores_check_for_non_dataformat_mode(self):
        helper.add_schema(
            classname="unittestschema", options={"keyname_mode": "edit"}, verbose=False
        )
        instance = Instance(classname="unittestschema", keyname="anything goes")
        self.assertTrue(instance.is_valid())


class TestInstanceMergeImportKeynameDataformat(TestCase):
    def setUp(self):
        """Reset the app-level cache before each test."""
        cache.clear()

    def test_merge_import_accepts_valid_keyname(self):
        helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        helper.add_instance(classname="unittestschema", keyname="10.1.2.0/24", verbose=False)

        qs = DataInstance.objects.filter(classname="unittestschema", keyname="10.1.2.0/24")
        self.assertEqual(len(qs), 1)

    def test_merge_import_rejects_invalid_keyname(self):
        """A malformed keyname is dropped by merge_import() itself - loader.py never
        calls Instance.is_valid(), so the format guarantee has to be enforced there."""
        helper.add_schema(
            classname="unittestschema",
            options={"keyname_mode": "dataformat ipv4 subnet strict"},
            verbose=False,
        )
        helper.add_instance(classname="unittestschema", keyname="not-an-ip", verbose=False)

        qs = DataInstance.objects.filter(classname="unittestschema")
        self.assertEqual(len(qs), 0)
