# (c) cavaliba.com - tests / data / exporter CSV stays aligned on injected columns

import io

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"]}


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

        helper.add_schema(
            classname="aliref",
            field_definition={
                "refstring": {"dataformat": "string", "displayname": "RefString"},
            },
        )
        helper.add_instance(
            classname="aliref",
            keyname="aliref-01",
            fields={"refstring": "referenced value"},
        )

        helper.add_schema(
            classname="alimain",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString", "order": 1},
                "myref": {
                    "dataformat": "schema",
                    "displayname": "MyRef",
                    "dataformat_ext": "aliref refstring",
                    "order": 2,
                },
            },
        )
        # first row references the target (so the injected subfield exists on it),
        # second row does not (so it has no such field at all)
        helper.add_instance(
            classname="alimain",
            keyname="alimain-01",
            fields={"mystring": "one", "myref": "aliref-01"},
        )
        helper.add_instance(
            classname="alimain",
            keyname="alimain-02",
            fields={"mystring": "two"},
        )

    def _csv(self, spec):
        out = io.StringIO()
        stats = export_write(spec, AAA, out)
        return out.getvalue().splitlines(), stats

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_every_row_has_as_many_cells_as_the_header(self):
        spec = ExportSpec(
            schema="alimain",
            format="csv",
            columns="_schema,keyname,mystring,myref,myref__refstring",
        )
        lines, stats = self._csv(spec)

        self.assertEqual(stats["count_ok"], 2)
        width = len(lines[0].split(","))
        for line in lines[1:]:
            self.assertEqual(len(line.split(",")), width)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_a_row_without_the_reference_gets_an_empty_cell(self):
        spec = ExportSpec(
            schema="alimain",
            format="csv",
            columns="_schema,keyname,mystring,myref__refstring",
        )
        lines, _stats = self._csv(spec)

        self.assertEqual(lines[0].split(","), ["_schema", "keyname", "mystring", "myref__refstring"])  # fmt: skip
        self.assertEqual(lines[1].split(","), ["alimain", "alimain-01", "one", "referenced value"])
        self.assertEqual(lines[2].split(","), ["alimain", "alimain-02", "two", ""])

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_filter_mode_keeps_one_width_by_leaving_injected_out(self):
        lines, stats = self._csv(ExportSpec(schema="alimain", format="csv"))

        self.assertEqual(stats["count_ok"], 2)
        self.assertNotIn("myref__refstring", lines[0].split(","))
        width = len(lines[0].split(","))
        for line in lines[1:]:
            self.assertEqual(len(line.split(",")), width)
