# (c) cavaliba.com - tests / views / admintools row triggers (no direct launch)

import re

from django.core.cache import cache as cache_django
from django.test import TestCase, override_settings
from django.urls import reverse

import app_home.cache as cache
from tests import helper

# every tool row: a <button> opening a confirm modal, or an <a> to a dedicated view
MODAL_TOOLS = [
    "#updateBigsetModal",
    "#eavRefreshModal",
    "#eavPurgeModal",
    "#ipamRefreshModal",
    "#housekeepingModal",
    "#factoryResetModal",
]

VIEW_TOOLS = [
    "app_home:admintools_keyname",
    "app_home:admintools_revision",
    "app_home:admintools_active_user",
]


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class TestAdmintoolsRowTriggers(TestCase):
    def setUp(self):
        cache.clear()
        cache_django.clear()
        helper.add_admin_user(login="unittest")

    def _html(self):
        response = self.client.get(reverse("app_home:admintools"), follow=True)
        self.assertEqual(response.status_code, 200)
        return response.content.decode()

    def test_no_right_side_action_buttons(self):
        html = self._html()
        self.assertNotIn("btn-outline-primary", html)
        self.assertNotIn("btn-outline-secondary", html)

    def test_every_row_is_a_trigger(self):
        html = self._html()
        rows = re.findall(r"<(a|button)\b[^>]*\bcv-admintools-row\b[^>]*>", html)
        # 6 modal tools + 3 dedicated views (UI Prototypes needs BETA_PREVIEW)
        self.assertEqual(len(rows), len(MODAL_TOOLS) + len(VIEW_TOOLS))

    def test_modal_rows_carry_their_modal_target(self):
        html = self._html()
        row_tags = re.findall(r"<button\b[^>]*\bcv-admintools-row\b[^>]*>", html)
        targets = set()
        for tag in row_tags:
            match = re.search(r'data-bs-target="(#[^"]+)"', tag)
            self.assertIsNotNone(match, f"row trigger opens no modal: {tag}")
            targets.add(match.group(1))
        self.assertEqual(targets, set(MODAL_TOOLS))

    def test_view_rows_are_links(self):
        html = self._html()
        for name in VIEW_TOOLS:
            url = reverse(name)
            pattern = rf'<a\b[^>]*href="{re.escape(url)}"[^>]*\bcv-admintools-row\b'
            self.assertRegex(html, pattern)

    def test_no_post_form_outside_the_modals(self):
        # the structural guard against a direct launch: every POST form lives in a
        # modal footer, below the MODALS marker - never inside a tool row
        html = self._html()
        marker = html.index("<!-- MODALS -->")
        self.assertNotIn('<form method="post"', html[:marker])

    def test_every_action_url_is_posted_from_a_modal_only(self):
        html = self._html()
        for name in [
            "app_home:admintools_updatebigset",
            "app_home:admintools_eavrefresh",
            "app_home:admintools_eavpurge",
            "app_home:admintools_ipamrefresh",
            "app_home:admintools_housekeeping",
        ]:
            url = reverse(name)
            self.assertEqual(html.count(url), 1)
            self.assertGreater(html.index(url), html.index("<!-- MODALS -->"))

    def test_no_leaked_template_comment(self):
        # {# ... #} is single-line only: a multi-line one is not parsed as a comment
        # and its text renders on the page
        html = self._html()
        self.assertNotIn("{#", html)
        self.assertNotIn("#}", html)
        self.assertNotIn("Every row is clickable", html)

    def test_icon_is_inside_the_row_trigger(self):
        html = self._html()
        # the icon column is no longer a <div> sibling of a button: it sits inside
        # the row trigger, so clicking it (or the label) fires the same action
        self.assertNotRegex(html, r'<div class="[^"]*cv-admintools-icon')
        self.assertRegex(html, r'<span class="[^"]*cv-admintools-icon')
