# (c) cavaliba.com - tests / data / fields

import app_home.cache as cache
from app_data.data import Instance
from app_data.fieldtypes.field_float import FieldFloat
from app_data.fieldtypes.field_int import FieldInt
from app_data.fieldtypes.field_ipv4 import FieldIPV4
from django.test import TestCase
from tests.helper import add_instance, add_schema


class TestDataFieldTypes(TestCase):

    fixtures = ["test"]

    def setUp(self):
        #cache.init()
        cache.clear()

    def test_field_values(self):

        instance = Instance.from_keyname(classname="test1", keyname="test1-01", expand=False)
        self.assertIsNotNone(instance)
        self.assertEqual(
            instance.fields["mystring"].get_value(),
            ["data for test1-01"])
        self.assertEqual(instance.fields["myint"].get_value(), [11])
        self.assertEqual(instance.fields["myfloat"].get_value(), [27.19])
        self.assertEqual(instance.fields["myboolean"].get_value(), [True])
        self.assertEqual(instance.fields["mydate"].get_value(), ["2024-11-01"])
        self.assertEqual(instance.fields["myipv4"].get_value(), ["10.1.2.3"])
        self.assertEqual(
            instance.fields["my_schema_test0"].get_value(),
            ["test0-01"])
        self.assertEqual(
            instance.fields["my_schema_test0_multi"].get_value(), [
                "test0-02", "test0-03"])
        self.assertEqual(
            instance.fields["my_schema_self"].get_value(),
            ["test1-03"])

    def test_default_value(self):
        instance = Instance(classname="test1")
        self.assertEqual(
            instance.fields["mystring_default"].get_value(),
            ["hello"])
        self.assertEqual(instance.fields["myint_default"].get_value(), [11])
        self.assertEqual(
            instance.fields["myint_default_multi"].get_value(), [
                11, 22])
        self.assertEqual(
            instance.fields["myfloat_default"].get_value(),
            [11.11])
        self.assertEqual(
            instance.fields["myfloat_default_multi"].get_value(), [
                11.11, 22.22])

    def test_boolean(self):

        instance = Instance(classname="test1")

        a = instance.fields["myboolean_default_true"].get_first_value()
        self.assertEqual(type(a), bool)
        self.assertTrue(a)

        b = instance.fields["myboolean_default_false"].get_first_value()
        self.assertEqual(type(b), bool)
        self.assertFalse(b)

    def test_external_no_expand(self):

        instance = Instance.from_keyname(classname="test4", keyname="test4-01", expand=False)
        self.assertIsNotNone(instance)
        self.assertIsNotNone(instance.fields["_test1"])
        self.assertFalse("test1" in instance.fields)

    def test_external_expand(self):

        instance = Instance.from_keyname(classname="test4", keyname="test4-01", expand=True)
        self.assertIsNotNone(instance)
        self.assertIsNotNone(instance.fields["_test1"])
        self.assertIsNotNone(instance.fields["test1"])
        self.assertIsNotNone(instance.fields["test1__mystring"])
        self.assertIsNotNone(instance.fields["test1__myint"])
        self.assertIsNotNone(instance.fields["test1__myfloat"])
        self.assertIsNotNone(instance.fields["test1__myboolean"])
        self.assertEqual(instance.fields["test1__myint"].get_value(), [11])
        self.assertEqual(
            instance.fields["test1__myfloat"].get_value(),
            [27.19])
        self.assertEqual(
            instance.fields["test1__myboolean"].get_value(),
            [True])
        self.assertEqual(
            instance.fields["test1__mystring"].get_value(),
            ["data for test1-01"])

    def test_enumerate_no_expand(self):

        instance = Instance.from_keyname(classname="test1", keyname="test1-01", expand=False)
        self.assertIsNotNone(instance)
        self.assertIsNotNone(instance.fields["my_enumerate_abcde"])
        self.assertEqual(
            instance.fields["my_enumerate_abcde"].get_value(), ["A"])
        self.assertIsNotNone(instance.fields["my_enumerate_abcde_multi"])
        self.assertTrue(
            "A" in instance.fields["my_enumerate_abcde_multi"].get_value())
        self.assertTrue(
            "B" in instance.fields["my_enumerate_abcde_multi"].get_value())
        self.assertTrue(
            "C" in instance.fields["my_enumerate_abcde_multi"].get_value())

        self.assertIsNotNone(instance.fields["my_enumerate_subfields"])
        self.assertEqual(
            instance.fields["my_enumerate_subfields"].get_value(), ["A"])
        self.assertFalse("my_enumerate_subfields__widget" in instance.fields)
        self.assertFalse(
            "my_enumerate_subfields__enumstring" in instance.fields)
        self.assertFalse("my_enumerate_subfields__enumint" in instance.fields)
        self.assertFalse(
            "my_enumerate_subfields__enumfloat" in instance.fields)
        self.assertFalse(
            "my_enumerate_subfields__enumboolean" in instance.fields)

    def test_enumerate_expand(self):

        instance = Instance.from_keyname(classname="test1", keyname="test1-01", expand=True)
        self.assertIsNotNone(instance)
        self.assertIsNotNone(instance.fields["my_enumerate_abcde"])
        self.assertEqual(
            instance.fields["my_enumerate_abcde"].get_value(), ["A"])
        self.assertIsNotNone(instance.fields["my_enumerate_abcde_multi"])
        self.assertTrue(
            "A" in instance.fields["my_enumerate_abcde_multi"].get_value())
        self.assertTrue(
            "B" in instance.fields["my_enumerate_abcde_multi"].get_value())
        self.assertTrue(
            "C" in instance.fields["my_enumerate_abcde_multi"].get_value())

        self.assertIsNotNone(instance.fields["my_enumerate_subfields"])
        self.assertEqual(
            instance.fields["my_enumerate_subfields"].get_value(), ["A"])
        self.assertTrue("my_enumerate_subfields__widget" in instance.fields)
        self.assertTrue(
            "my_enumerate_subfields__enumstring" in instance.fields)
        self.assertTrue("my_enumerate_subfields__enumint" in instance.fields)
        self.assertTrue("my_enumerate_subfields__enumfloat" in instance.fields)
        self.assertTrue(
            "my_enumerate_subfields__enumboolean" in instance.fields)
        self.assertTrue(
            "my_enumerate_subfields__enumdate" in instance.fields)

        self.assertEqual(
            instance.fields["my_enumerate_subfields__enumint"].get_value(),
            [111])
        self.assertEqual(
            instance.fields["my_enumerate_subfields__enumfloat"].get_value(),
            [111.1])
        self.assertEqual(
            instance.fields["my_enumerate_subfields__enumstring"].get_value(),
            ["AAA"])
        self.assertEqual(
            instance.fields["my_enumerate_subfields__enumboolean"].get_value(),
            [False])
        self.assertEqual(
            instance.fields["my_enumerate_subfields__enumdate"].get_value(),
            ["2026-01-15"])
        self.assertEqual(
            instance.fields["my_enumerate_subfields__widget"].get_value(),
            ["&#x1F7E2;"])


# my_enumerate_subfields__enumstring
#     from: my_enumerate_subfields : A
# - Widget:
#     from: my_enumerate_subfields__widget : green_circle
# - String:
#     from: my_enumerate_subfields__enumstring   : AAA
# - Boolean:
#     from: my_enumerate_subfields__enumboolean : False
# - Int:
#     from: my_enumerate_subfields__enumint : 111
    # - Float:
    #     from: my_enumerate_subfields__enumfloat : 111.1

    def test_int_valid(self):

        fieldschema = {
            'cardinal_min': 0,
            'cardinal_max': 1,
            'default_value': ''}

        # OK
        f = FieldInt(
            fieldname='data',
            fieldschema=fieldschema,
            alljson={
                'data': [33]})
        self.assertEqual(f.is_valid(), True)
        f = FieldInt(fieldname='data',
                     fieldschema=fieldschema,
                     alljson={'data': [-3]})
        self.assertEqual(f.is_valid(), True)

        # KO
        f = FieldInt(
            fieldname='data',
            fieldschema=fieldschema,
            alljson={
                'data': ["a"]})
        self.assertEqual(f.is_valid(), False)
        f = FieldInt(
            fieldname='data',
            fieldschema=fieldschema,
            alljson={
                'data': [33.4]})
        self.assertEqual(f.is_valid(), False)

    def test_float_valid(self):

        fieldschema = {
            'cardinal_min': 0,
            'cardinal_max': 1,
            'default_value': ''}

        # OK
        f = FieldFloat(
            fieldname='data',
            fieldschema=fieldschema,
            alljson={
                'data': [33.2]})
        self.assertEqual(f.is_valid(), True)

        # KO
        f = FieldFloat(
            fieldname='data',
            fieldschema=fieldschema,
            alljson={
                'data': ["a"]})
        self.assertEqual(f.is_valid(), False)

    def test_ipv4_valid(self):

        fieldschema = {
            'cardinal_min': 0,
            'cardinal_max': 1,
            'default_value': ''}

        # OK
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['10.1.2.3']})
        self.assertEqual(f.is_valid(), True)
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['0.0.0.0']})
        self.assertEqual(f.is_valid(), True)
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['255.255.255.255']})
        self.assertEqual(f.is_valid(), True)

        # KO
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['10.1.2.3/24']})
        self.assertEqual(f.is_valid(), False)
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['10.1.2.256']})
        self.assertEqual(f.is_valid(), False)
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['10.1.2']})
        self.assertEqual(f.is_valid(), False)
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['10.1.2.3.4']})
        self.assertEqual(f.is_valid(), False)
        f = FieldIPV4(
            fieldname='myip',
            fieldschema=fieldschema,
            alljson={
                'myip': ['10.1.2.3/33']})
        self.assertEqual(f.is_valid(), False)


class TestFieldUserMissingUser(TestCase):

    def setUp(self):
        cache.clear()

    def test_user_field_missing_user_shows_placeholder(self):
        add_schema(classname='schema_with_user', field_definition={
            'owner': {
                'displayname': 'Owner',
                'dataformat': 'user',
            }
        })
        add_instance(classname='schema_with_user', keyname='item-01', fields={
            'owner': 'nonexistent-login'
        })

        instance = Instance.from_keyname(classname='schema_with_user', keyname='item-01')
        self.assertIsNotNone(instance)

        datapoint = instance.fields['owner'].get_datapoint_ui_detail()

        self.assertEqual(len(datapoint["value"]), 1)
        self.assertEqual(datapoint["value"][0]["display"], "?? - nonexistent-login")


class TestFieldSchemaMissingInstance(TestCase):

    def setUp(self):
        cache.clear()

    def test_schema_field_missing_instance_shows_placeholder(self):
        add_schema(classname='target_schema')
        add_schema(classname='source_schema', field_definition={
            'ref_field': {
                'displayname': 'Reference Field',
                'dataformat': 'schema',
                'dataformat_ext': 'target_schema',
            }
        })
        add_instance(classname='source_schema', keyname='source-01', fields={
            'ref_field': 'nonexistent-key'
        })

        instance = Instance.from_keyname(classname='source_schema', keyname='source-01')
        self.assertIsNotNone(instance)

        datapoint = instance.fields['ref_field'].get_datapoint_ui_detail()

        self.assertEqual(len(datapoint["value"]), 1)
        self.assertEqual(datapoint["value"][0]["display"], "?? - nonexistent-key")
