# (c) cavaliba.com - tests CSV dataview export: pure passthrough, no forced columns

from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from app_data.data import Instance
from app_data.dataview import DataView
from tests import helper


class TestDataViewGetCsvFieldnames(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_schema(
            classname="csvpassthrough",
            field_definition={
                "keep_me": {"dataformat": "string", "displayname": "Keep Me"},
                "drop_me": {"dataformat": "string", "displayname": "Drop Me"},
            },
        )
        helper.add_instance(
            classname="_dataview",
            keyname="csvpassthrough_plain",
            fields={
                "target_class": "csvpassthrough",
                "content": "columns:\n  - keep_me\n  - drop_me\n",
            },
        )
        helper.add_instance(
            classname="_dataview",
            keyname="csvpassthrough_renamed",
            fields={
                "target_class": "csvpassthrough",
                "content": "columns:\n  - Kept:\n      from: keep_me\n  - Kept again:\n      from: keep_me\n",
            },
        )
        helper.add_instance(
            classname="_dataview",
            keyname="csvpassthrough_no_identity",
            fields={
                "target_class": "csvpassthrough",
                "content": "columns:\n  - keep_me\n",
            },
        )

    def test_real_fieldnames_no_labels(self):
        dataview = DataView(keyname="csvpassthrough_renamed")
        fieldnames = dataview.get_csv_fieldnames()
        self.assertEqual(fieldnames, ["keep_me"])
        self.assertNotIn("Kept", fieldnames)
        self.assertNotIn("Kept again", fieldnames)

    def test_duplicate_source_deduplicated(self):
        dataview = DataView(keyname="csvpassthrough_renamed")
        fieldnames = dataview.get_csv_fieldnames()
        self.assertEqual(len(fieldnames), 1)

    def test_no_forced_classname_or_keyname(self):
        dataview = DataView(keyname="csvpassthrough_no_identity")
        fieldnames = dataview.get_csv_fieldnames()
        self.assertEqual(fieldnames, ["keep_me"])
        self.assertNotIn("classname", fieldnames)
        self.assertNotIn("keyname", fieldnames)


class TestDataViewGetCsvExportColumns(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_schema(
            classname="csvoverride",
            field_definition={
                "alpha": {"dataformat": "string", "displayname": "Alpha"},
                "beta": {"dataformat": "string", "displayname": "Beta"},
            },
        )
        helper.add_instance(
            classname="_dataview",
            keyname="csvoverride_view",
            fields={
                "target_class": "csvoverride",
                "content": "columns:\n  - alpha\n  - beta\n",
            },
        )

    def test_no_override_uses_view_fieldnames(self):
        dataview = DataView(keyname="csvoverride_view")
        self.assertEqual(dataview.get_csv_export_columns(None), ["alpha", "beta"])

    def test_explicit_override_replaces_view_fieldnames(self):
        dataview = DataView(keyname="csvoverride_view")
        self.assertEqual(dataview.get_csv_export_columns("alpha"), ["alpha"])

    def test_explicit_override_deduplicated(self):
        dataview = DataView(keyname="csvoverride_view")
        self.assertEqual(dataview.get_csv_export_columns("alpha,alpha,beta"), ["alpha", "beta"])

    def test_explicit_override_can_name_builtin_attribute(self):
        dataview = DataView(keyname="csvoverride_view")
        self.assertEqual(dataview.get_csv_export_columns("keyname,alpha"), ["keyname", "alpha"])


class TestDataViewGetCsvExportRow(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_schema(
            classname="csvrowtest",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString"},
            },
        )
        helper.add_instance(
            classname="csvrowtest",
            keyname="obj01",
            fields={"mystring": "value1"},
        )
        helper.add_instance(
            classname="_dataview",
            keyname="csvrowtest_view",
            fields={
                "target_class": "csvrowtest",
                "content": "columns:\n  - mystring\n",
            },
        )

    def test_row_matches_requested_columns(self):
        instance = Instance.from_keyname("csvrowtest", "obj01")
        dataview = DataView(keyname="csvrowtest_view")
        row = dataview.get_csv_export_row(instance, ["mystring", "keyname"])
        self.assertEqual(row, ["value1", "obj01"])


class DataExportCsvDataviewPassthroughViewTest(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")
        helper.add_schema(
            classname="csvviewtest",
            field_definition={
                "keep_me": {"dataformat": "string", "displayname": "Keep Me"},
                "drop_me": {"dataformat": "string", "displayname": "Drop Me"},
            },
        )
        helper.add_instance(
            classname="csvviewtest",
            keyname="obj01",
            fields={"keep_me": "keepvalue", "drop_me": "dropvalue"},
        )
        helper.add_instance(
            classname="_dataview",
            keyname="csvviewtest_view",
            fields={
                "target_class": "csvviewtest",
                "content": "columns:\n  - keep_me\n",
            },
        )

    def _post(self, extra=None):
        data = {
            "classname": "csvviewtest",
            "page": "allpages",
            "dv": "csvviewtest_view",
            "query": "",
            "format": "csv",
        }
        if extra:
            data.update(extra)
        return self.client.post(reverse("app_data:data_export"), data)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_header_is_exactly_view_fieldnames_no_identity_forced(self):
        response = self._post()
        self.assertEqual(response.status_code, 200)
        header = response.content.decode().strip().splitlines()[0]
        self.assertEqual(header, "keep_me")

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_drop_me_absent_when_not_in_view(self):
        response = self._post()
        content = response.content.decode()
        self.assertIn("keepvalue", content)
        self.assertNotIn("dropvalue", content)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_dv_fields_override_controls_output(self):
        response = self._post({"dv_fields": "drop_me"})
        content = response.content.decode()
        header = content.strip().splitlines()[0]
        self.assertEqual(header, "drop_me")
        self.assertIn("dropvalue", content)
        self.assertNotIn("keepvalue", content)
