# (c) cavaliba.com - tests / data / exporter enumerate subfields follow their parent column

import io

import yaml
from django.test import TestCase, override_settings

import app_home.cache as cache
from app_data.exporter import ExportSpec, export_write
from tests import helper

AAA = {"username": "unittest", "perms": ["p_data_admin"]}

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


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

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

        helper.add_schema(
            classname="enumsub",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString", "order": 1},
                "myenum": {
                    "dataformat": "enumerate",
                    "displayname": "MyEnum",
                    "dataformat_ext": "enumsub_enum",
                    "order": 2,
                },
            },
        )
        helper.add_instance(
            classname="enumsub",
            keyname="enumsub-01",
            fields={"mystring": "hello", "myenum": "A"},
        )

    def _yaml(self, spec):
        out = io.StringIO()
        export_write(spec, AAA, out)
        return yaml.safe_load(out.getvalue())

    # ---------------------------------------------------------------
    # explicit mode (what the Exporter UI always sends)
    # ---------------------------------------------------------------

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_subfields_added_when_the_enumerate_column_is_selected(self):
        spec = ExportSpec(schema="enumsub", format="yaml", columns="keyname,myenum")
        data = self._yaml(spec)

        self.assertIn("myenum__widget", data[0])
        self.assertIn("myenum__enumstring", data[0])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_subfields_come_right_after_their_parent(self):
        spec = ExportSpec(schema="enumsub", format="yaml", columns="keyname,myenum,mystring")
        keys = list(self._yaml(spec)[0])

        self.assertEqual(keys.index("myenum") + 1, keys.index("myenum__widget"))
        self.assertLess(keys.index("myenum__enumstring"), keys.index("mystring"))

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_no_subfields_when_the_enumerate_column_is_not_selected(self):
        spec = ExportSpec(schema="enumsub", format="yaml", columns="keyname,mystring")
        data = self._yaml(spec)

        self.assertNotIn("myenum__widget", data[0])
        self.assertNotIn("myenum", data[0])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_an_explicitly_named_subfield_is_not_duplicated(self):
        spec = ExportSpec(schema="enumsub", format="yaml", columns="keyname,myenum__widget,myenum")
        keys = list(self._yaml(spec)[0])

        self.assertEqual(keys.count("myenum__widget"), 1)

    # ---------------------------------------------------------------
    # filter mode (API / CLI callers)
    # ---------------------------------------------------------------

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_filter_mode_keeps_subfields_of_an_exported_enumerate(self):
        data = self._yaml(ExportSpec(schema="enumsub", format="yaml"))

        self.assertIn("myenum", data[0])
        self.assertIn("myenum__widget", data[0])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_filter_mode_drops_subfields_whose_parent_was_filtered_out(self):
        data = self._yaml(ExportSpec(schema="enumsub", format="yaml", columns="!myenum"))

        self.assertNotIn("myenum", data[0])
        self.assertNotIn("myenum__widget", data[0])

    # ---------------------------------------------------------------
    # CSV never grows a subfield column
    # ---------------------------------------------------------------

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_csv_keeps_one_fixed_header(self):
        out = io.StringIO()
        spec = ExportSpec(schema="enumsub", format="csv", columns="keyname,myenum")
        export_write(spec, AAA, out)
        header = out.getvalue().splitlines()[0].split(",")

        self.assertEqual(header, ["_schema", "keyname", "myenum"])
