# (c) cavaliba.com - tests / data / exporter progress modal footer vs p_task_view

import shutil
import tempfile

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

import app_home.cache as cache
from app_data.exporter import ExportSpec
from app_data.loader import load_broker
from app_data.models import DataTask
from app_data.task_manager import create_datatask
from app_user.models import SirenePermission
from tests import helper

AAA = {"username": "unittest", "perms": ["p_data_admin"]}
BASE_PERMS = ["p_data_export", "p_data_access", "p_data_read"]


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class ViewExporterModalButtonsTest(TestCase):
    def _isolate_filestore(self):
        """Point the filestore at a throwaway directory for this test."""

        rootdir = tempfile.mkdtemp(prefix="cavaliba_test_filestore_")
        override = override_settings(CAVALIBA_FILESTORE=rootdir)
        override.enable()
        self.addCleanup(override.disable)
        self.addCleanup(shutil.rmtree, rootdir, ignore_errors=True)
        return rootdir

    def setUp(self):
        self._isolate_filestore()
        cache.clear()
        helper.add_user_with_perm(login="unittest", perms=BASE_PERMS)
        helper.add_schema(
            classname="vbtn",
            field_definition={
                "mystring": {"dataformat": "string", "displayname": "MyString"},
            },
        )
        helper.add_instance(classname="vbtn", keyname="vbtn-01", fields={"mystring": "one"})

        self.params = {"spec": ExportSpec(schema="vbtn", format="csv").to_dict(), "aaa": AAA}
        self.task = create_datatask(
            name="Export csv - vbtn", params=self.params, owner_type="user", owner_id="unittest"
        )

    def _grant_task_view(self):
        for perm_name in [*BASE_PERMS, "p_task_view"]:
            SirenePermission.objects.get_or_create(keyname=perm_name)
        load_broker(
            datalist=[
                {
                    "classname": "role",
                    "_action": "update",
                    "keyname": "role_unittest",
                    "permissions": [*BASE_PERMS, "p_task_view"],
                }
            ],
            aaa={"perms": ["p_role_update"]},
        )
        cache.clear()

    def _running(self):
        DataTask.objects.filter(handle=self.task.handle).update(state="RUNNING")

    def _done(self):
        DataTask.objects.filter(handle=self.task.handle).update(state="DONE")

    def _get(self):
        return self.client.get(reverse("app_data:data_exporter_progress", args=[self.task.handle]))

    # ---------------------------------------------------------------
    # running, without p_task_view : abort only, no way to dismiss
    # ---------------------------------------------------------------

    def test_running_without_task_view_offers_abort_only(self):
        self._running()

        response = self._get()

        self.assertNotIn("ui_perm_task", response.context)
        self.assertContains(response, "Abort")
        self.assertNotContains(response, "data-bs-dismiss")

    def test_running_without_task_view_has_no_hide(self):
        self._running()

        response = self._get()

        self.assertNotContains(response, ">Hide<")
        self.assertNotContains(response, ">Close<")

    def test_queued_without_task_view_offers_abort_only(self):
        # QUEUED counts as running for the footer
        response = self._get()

        self.assertEqual(self.task.state, "QUEUED")
        self.assertContains(response, "Abort")
        self.assertNotContains(response, "data-bs-dismiss")

    # ---------------------------------------------------------------
    # running, with p_task_view : abort + hide
    # ---------------------------------------------------------------

    def test_running_with_task_view_offers_abort_and_hide(self):
        self._grant_task_view()
        self._running()

        response = self._get()

        self.assertTrue(response.context["ui_perm_task"])
        self.assertContains(response, "Abort")
        self.assertContains(response, "data-bs-dismiss")
        self.assertContains(response, "Hide")

    def test_running_with_task_view_does_not_say_close(self):
        self._grant_task_view()
        self._running()

        response = self._get()

        self.assertNotContains(response, ">Close<")

    # ---------------------------------------------------------------
    # terminal : close for everyone, abort gone
    # ---------------------------------------------------------------

    def test_done_without_task_view_can_still_close(self):
        # the export is over and the result link is in the body; without a Close
        # the user would be stuck (static backdrop, no keyboard, no "x")
        self._done()

        response = self._get()

        self.assertContains(response, "data-bs-dismiss")
        self.assertContains(response, "Close")
        self.assertNotContains(response, "Abort")

    def test_done_with_task_view_also_says_close_not_hide(self):
        self._grant_task_view()
        self._done()

        response = self._get()

        self.assertContains(response, "Close")
        self.assertNotContains(response, ">Hide<")
        self.assertNotContains(response, "Abort")

    def test_aborted_offers_close_only(self):
        DataTask.objects.filter(handle=self.task.handle).update(state="ABORTED")

        response = self._get()

        self.assertContains(response, "Close")
        self.assertNotContains(response, "Abort<")

    # ---------------------------------------------------------------
    # the modal itself must have no other exit, or the above is moot
    # ---------------------------------------------------------------

    def test_modal_shell_cannot_be_dismissed_another_way(self):
        from django.template.loader import get_template

        source = get_template("app_data/exporter.html").template.source

        self.assertIn('data-bs-backdrop="static"', source)
        self.assertIn('data-bs-keyboard="false"', source)
        self.assertNotIn("btn-close", source)
