# (c) cavaliba.com - tests / view import csv

from django.core.files.uploadedfile import SimpleUploadedFile
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 tests import helper


class ViewImportCsvTest(TestCase):
    def setUp(self):
        cache.clear()
        helper.add_admin_user(login="unittest")
        helper.add_schema(
            classname="csvtest",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString"},
            },
        )

    def _post_csv(self, content, submit, extra=None, follow=False):
        data = {
            "mode": "csv",
            "file": SimpleUploadedFile(
                "data.csv", content.encode("utf-8"), content_type="text/csv"
            ),
            "schema": "csvtest",
            "pipeline": "",
            "encoding": "utf-8",
            "separator": ",",
            "submit": submit,
        }
        if extra:
            data.update(extra)
        return self.client.post(reverse("app_data:data_import"), data, follow=follow)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_verify_reports_row_and_error_counts(self):
        response = self._post_csv("keyname,mystring\nrow1,hello\n", "verify")
        self.assertEqual(response.status_code, 200)
        rendered = [str(m) for m in response.context["messages"]]
        self.assertTrue(any("1 rows" in m and "0 error" in m for m in rendered))

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_import_creates_instance(self):
        response = self._post_csv("keyname,mystring\nrow1,hello\n", "import")
        self.assertEqual(response.status_code, 302)
        instance = Instance.from_keyname(classname="csvtest", keyname="row1", expand=False)
        self.assertIsNotNone(instance)

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_import_ok_ko_message(self):
        response = self._post_csv(
            "keyname,mystring\nrow1,hello\nrow2,world\n", "import", follow=True
        )
        rendered = [str(m) for m in response.context["messages"]]
        self.assertTrue(any("Import OK" in m and "(2)" in m for m in rendered))

    @override_settings(CAVALIBA_AUTH_MODE="unittest", CAVALIBA_CSV_IMPORT_MAX_FAILURE=2)
    def test_import_aborts_past_failure_threshold(self):
        """Every row targets a non-existent schema, so load_broker fails on each one;
        once failures exceed CAVALIBA_CSV_IMPORT_MAX_FAILURE, the loop stops early."""

        rows = "\n".join(f"row{i},doesnotexist" for i in range(1, 8))
        content = "keyname,schema\n" + rows + "\n"
        response = self._post_csv(content, "import", follow=True)

        rendered = [str(m) for m in response.context["messages"]]
        self.assertTrue(any("aborted" in m.lower() for m in rendered))

    @override_settings(CAVALIBA_AUTH_MODE="unittest")
    def test_error_subset_capped_at_20(self):
        rows = "\n".join(f"row{i}" for i in range(1, 30))
        content = "mystring\n" + rows + "\n"  # no "keyname" column: every row errors
        response = self._post_csv(content, "verify")
        rendered = [str(m) for m in response.context["messages"]]
        error_lines = [m for m in rendered if m.startswith("row")]
        self.assertLessEqual(len(error_lines), 20)
