# (c) cavaliba.com - test_schema_option

from django.test import TestCase

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


class TestSchemaOption(TestCase):

    def setUp(self):
        cache.clear()

    # ---------------------------
    # keyname_mode
    # ---------------------------

    def test_keyname_mode_edit(self):
        schema = helper.add_schema(
            classname="unittestschema",
            displayname="Unittest Schema",
            options={"icon": "testicon", "keyname_mode": "edit"},
            verbose=False,
        )

        self.assertIsNotNone(schema)
        self.assertIn("keyname_mode", schema.options)
        self.assertEqual(schema.keyname_mode, "edit")

    # ---------------------------

    def test_keyname_mode_auto(self):
        schema = helper.add_schema(
            classname="unittestschema",
            displayname="Unittest Schema",
            options={"icon": "testicon", "keyname_mode": "auto"},
            verbose=False,
        )

        self.assertIsNotNone(schema)
        self.assertIn("keyname_mode", schema.options)
        self.assertEqual(schema.keyname_mode, "auto")

    # ---------------------------

    def test_keyname_mode_default(self):
        schema = helper.add_schema(
            classname="unittestschema", displayname="Unittest Schema", verbose=False
        )

        self.assertIsNotNone(schema)
        self.assertEqual(schema.keyname_mode, "edit")

    # ---------------------------

    def test_keyname_mode_invalid(self):
        schema = helper.add_schema(
            classname="unittestschema",
            displayname="Unittest Schema",
            options={"icon": "testicon", "keyname_mode": "invalid"},
            verbose=False,
        )

        self.assertIsNotNone(schema)
        self.assertEqual(schema.keyname_mode, "edit")

    # ---------------------------

    def test_keyname_mode_auto_result(self):
        helper.add_schema(
            classname="unittestschema",
            displayname="Unittest Schema",
            options={"icon": "testicon", "keyname_mode": "auto"},
            verbose=False,
        )

        helper.add_instance("unittestschema", keyname="utest01", verbose=False)
        helper.add_instance("unittestschema", verbose=False)

        schema = Schema.from_name("unittestschema")
        self.assertIsNotNone(schema)
        self.assertIn("keyname_mode", schema.options)
        self.assertEqual(schema.keyname_mode, "auto")

        inst1 = Instance.from_keyname(classname="unittestschema", keyname="utest01")
        self.assertIsNone(inst1)

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

        for obj in qs:
            k = obj.keyname
            self.assertEqual(len(k), 36)

    # ---------------------------
    # field_hide_from_detail
    # ---------------------------

    def test_field_hide_from_detail_default_is_empty_list(self):
        schema = helper.add_schema(classname="unittestschema", verbose=False)
        self.assertEqual(schema.field_hide_from_detail, [])

    # ---------------------------

    def test_field_hide_from_detail_valid_list_stored(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_detail": ["field1", "field2"]},
            verbose=False,
        )
        self.assertEqual(schema.field_hide_from_detail, ["field1", "field2"])

    # ---------------------------

    def test_field_hide_from_detail_non_list_coerced_to_empty(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_detail": "field1"},
            verbose=False,
        )
        self.assertEqual(schema.field_hide_from_detail, [])

    # ---------------------------

    def test_field_hide_from_detail_non_string_items_filtered(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_detail": ["field1", 42, None, "field2"]},
            verbose=False,
        )
        self.assertEqual(schema.field_hide_from_detail, ["field1", "field2"])

    # ---------------------------

    def test_field_hide_from_detail_to_dict_includes_when_set(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_detail": ["field1"]},
            verbose=False,
        )
        d = schema.to_dict()
        self.assertIn("field_hide_from_detail", d["_options"])
        self.assertEqual(d["_options"]["field_hide_from_detail"], ["field1"])

    # ---------------------------

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

    # ---------------------------

    def test_field_hide_from_detail_hides_field_in_ui_detail(self):
        helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_detail": ["myfield"]},
            field_definition={"myfield": {"dataformat": "text"}, "otherfield": {"dataformat": "text"}},
            verbose=False,
        )
        helper.add_instance(
            classname="unittestschema",
            keyname="inst01",
            fields={"myfield": "secret", "otherfield": "visible"},
        )

        instance = Instance.from_keyname(classname="unittestschema", keyname="inst01")
        ui = instance.get_dict_for_ui_detail()

        self.assertNotIn("myfield", ui)
        self.assertIn("otherfield", ui)

    # ---------------------------

    def test_field_hide_from_detail_unknown_field_ignored(self):
        helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_detail": ["nonexistent_field"]},
            field_definition={"realfield": {"dataformat": "text"}},
            verbose=False,
        )
        helper.add_instance(
            classname="unittestschema",
            keyname="inst01",
            fields={"realfield": "value"},
        )

        instance = Instance.from_keyname(classname="unittestschema", keyname="inst01")
        ui = instance.get_dict_for_ui_detail()

        self.assertIn("realfield", ui)


# ---------------------------
# field_hide_from_edit
# ---------------------------


class TestSchemaFieldHideFromEdit(TestCase):

    def setUp(self):
        cache.clear()

    def test_field_hide_from_edit_default_is_empty_list(self):
        schema = helper.add_schema(classname="unittestschema", verbose=False)
        self.assertEqual(schema.field_hide_from_edit, [])

    # ---------------------------

    def test_field_hide_from_edit_valid_list_stored(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_edit": ["field1", "field2"]},
            verbose=False,
        )
        self.assertEqual(schema.field_hide_from_edit, ["field1", "field2"])

    # ---------------------------

    def test_field_hide_from_edit_non_list_coerced_to_empty(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_edit": "field1"},
            verbose=False,
        )
        self.assertEqual(schema.field_hide_from_edit, [])

    # ---------------------------

    def test_field_hide_from_edit_non_string_items_filtered(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_edit": ["field1", 42, None, "field2"]},
            verbose=False,
        )
        self.assertEqual(schema.field_hide_from_edit, ["field1", "field2"])

    # ---------------------------

    def test_field_hide_from_edit_to_dict_includes_when_set(self):
        schema = helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_edit": ["field1"]},
            verbose=False,
        )
        d = schema.to_dict()
        self.assertIn("field_hide_from_edit", d["_options"])
        self.assertEqual(d["_options"]["field_hide_from_edit"], ["field1"])

    # ---------------------------

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

    # ---------------------------

    def test_field_hide_from_edit_hides_field_in_ui_form(self):
        helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_edit": ["myfield"]},
            field_definition={"myfield": {"dataformat": "text"}, "otherfield": {"dataformat": "text"}},
            verbose=False,
        )
        helper.add_instance(
            classname="unittestschema",
            keyname="inst01",
            fields={"myfield": "secret", "otherfield": "visible"},
        )

        instance = Instance.from_keyname(classname="unittestschema", keyname="inst01")
        ui = instance.get_dict_for_ui_form()

        all_field_names = [
            dp["fieldname"]
            for page_data in ui["PAGES"].values()
            for order_data in page_data.values()
            for dp in order_data
        ]
        self.assertNotIn("myfield", all_field_names)
        self.assertIn("otherfield", all_field_names)

    # ---------------------------

    def test_field_hide_from_edit_unknown_field_ignored(self):
        helper.add_schema(
            classname="unittestschema",
            options={"field_hide_from_edit": ["nonexistent_field"]},
            field_definition={"realfield": {"dataformat": "text"}},
            verbose=False,
        )
        helper.add_instance(
            classname="unittestschema",
            keyname="inst01",
            fields={"realfield": "value"},
        )

        instance = Instance.from_keyname(classname="unittestschema", keyname="inst01")
        ui = instance.get_dict_for_ui_form()

        all_field_names = [
            dp["fieldname"]
            for page_data in ui["PAGES"].values()
            for order_data in page_data.values()
            for dp in order_data
        ]
        self.assertIn("realfield", all_field_names)
