# (c) cavaliba.com - tests / data / exporter column selector catalog

from django.test import TestCase, override_settings

import app_home.cache as cache
from app_data.exporter import EXPORT_MANDATORY_FIELDS, export_column_catalog
from tests import helper

ENUM_CONTENT = (
    '- value: "A"\n'
    '  widget: "green_circle"\n'
    "  enumstring: string AAA\n"
    '- value: "B"\n'
    '  widget: "yellow_circle"\n'
)


class ExporterColumnCatalogTest(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")

        helper.add_instance(
            classname="_enumerate",
            keyname="colcat_enum",
            fields={"content": ENUM_CONTENT},
        )

        helper.add_schema(
            classname="colcatref",
            field_definition={
                "refstring": {"dataformat": "string", "displayname": "RefString"},
            },
        )

        helper.add_schema(
            classname="colcat",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString", "order": 1},
                "myref": {
                    "dataformat": "schema",
                    "displayname": "MyRef",
                    "dataformat_ext": "colcatref refstring",
                    "order": 2,
                },
                "myenum": {
                    "dataformat": "enumerate",
                    "displayname": "MyEnum",
                    "dataformat_ext": "colcat_enum",
                    "order": 3,
                },
            },
        )
        helper.add_instance(
            classname="colcat",
            keyname="colcat-01",
            fields={"mystring": "hello", "myenum": "A"},
        )

    def _names(self, catalog):
        return [entry["name"] for entry in catalog]

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_no_schema_means_no_columns(self):
        self.assertEqual(export_column_catalog(""), [])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_mandatory_columns_come_first_and_are_flagged(self):
        catalog = export_column_catalog("colcat")

        self.assertEqual(self._names(catalog)[:2], list(EXPORT_MANDATORY_FIELDS))
        self.assertTrue(catalog[0]["mandatory"])
        self.assertTrue(catalog[1]["mandatory"])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_builtin_attributes_are_offered(self):
        names = self._names(export_column_catalog("colcat"))

        for name in ("displayname", "is_enabled", "last_sync", "last_update"):
            self.assertIn(name, names)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_builtins_then_schema_fields_then_injected(self):
        names = self._names(export_column_catalog("colcat"))

        self.assertLess(names.index("last_update"), names.index("mystring"))
        self.assertLess(names.index("mystring"), names.index("myref"))
        self.assertLess(names.index("myref"), names.index("myref__refstring"))

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_schema_field_carries_its_displayname_as_label(self):
        entry = next(e for e in export_column_catalog("colcat") if e["name"] == "mystring")

        self.assertEqual(entry["label"], "MyString")
        self.assertEqual(entry["group"], "schema")
        self.assertFalse(entry["mandatory"])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_injected_subfield_offered_although_the_sample_row_has_no_reference(self):
        # colcat-01 leaves myref empty, so the subfield exists on no loaded field
        entry = next(e for e in export_column_catalog("colcat") if e["name"] == "myref__refstring")

        self.assertEqual(entry["group"], "injected")

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_enumerate_subfields_are_not_offered(self):
        names = self._names(export_column_catalog("colcat"))

        self.assertIn("myenum", names)
        self.assertNotIn("myenum__widget", names)
        self.assertNotIn("myenum__enumstring", names)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_every_name_is_listed_once(self):
        names = self._names(export_column_catalog("colcat"))

        self.assertEqual(len(names), len(set(names)))
