# (c) cavaliba.com - test / field templates / end-to-end call sites

"""
The golden-markup files (test_field_render_{list,detail,print,edit}.py) render
one datapoint through the field-template layer in isolation. This file covers
the other half: that the real views still *reach* that layer and pass the mode
they are supposed to.

Without these, phase 1/3 of the unification could rewire a call site to the
wrong display_mode (or drop the include altogether) with every golden test
still green - see project/claude_doc/2026-10-03-FIELD-TEMPLATE-UNIFICATION-DONE.md.
"""

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

import app_home.cache as cache
from app_data.models import DataInstance
from tests import helper


@override_settings(CAVALIBA_AUTH_MODE="unittest")
class TestFieldRenderViews(TestCase):
    def setUp(self):
        """fieldrender schema + instance + an admin user logged in through the
        unittest auth mode."""
        cache.clear()
        helper.add_admin_user(login="unittest")
        self.instance = helper.add_fieldrender_fixture()
        self.obj = DataInstance.objects.get(
            classname=helper.FIELDRENDER_CLASSNAME, keyname=helper.FIELDRENDER_KEYNAME
        )
        self.site01 = helper.site_id("site01")

    def test_instance_list_renders_list_mode_cells(self):
        url = reverse("app_data:instance_list", kwargs={"classname": helper.FIELDRENDER_CLASSNAME})
        response = self.client.get(f"{url}?dv={helper.FIELDRENDER_DATAVIEW}")
        self.assertEqual(response.status_code, 200)
        body = helper.normalize_html(response.content.decode())
        # list mode markers: schema cell link, right-aligned int, truncated text
        self.assertIn(
            '<a class="cv-schema-cell-link" '
            f'href="/data/private/instance/detail/{self.site01}/">Site 01</a>',
            body,
        )
        self.assertIn('<div class="d-flex flex-wrap justify-content-end"> 42 </div>', body)
        self.assertIn("elit sed do e…</pre>", body)
        # and NOT detail-mode markup
        self.assertNotIn("btn btn-outline-success btn-sm", body)

    def test_instance_detail_renders_detail_mode_cells(self):
        response = self.client.get(reverse("app_data:instance_detail", kwargs={"id": self.obj.id}))
        self.assertEqual(response.status_code, 200)
        body = helper.normalize_html(response.content.decode())
        self.assertIn(
            '<a class="btn btn-outline-success btn-sm mx-1 my-1" '
            f'href="/data/private/instance/detail/{self.site01}/" role="button"> Site 01</a>',
            body,
        )
        # detail mode shows the full text, not the list-mode truncation
        self.assertIn(f"<pre>{helper.LONG_TEXT}</pre>", body)
        self.assertNotIn("cv-schema-cell-link", body)

    def test_instance_print_renders_print_mode_cells(self):
        url = reverse("app_data:instance_detail", kwargs={"id": self.obj.id})
        response = self.client.get(f"{url}?print=1")
        self.assertEqual(response.status_code, 200)
        body = helper.normalize_html(response.content.decode())
        # print mode drops the links around schema references and files
        self.assertIn('<div class="d-flex flex-wrap"> Site 01 </div>', body)
        self.assertNotIn("btn btn-outline-success btn-sm", body)
        self.assertNotIn("cv-schema-cell-link", body)
        self.assertNotIn(f"/data/private/file/{helper.FIELDRENDER_FILEID}/", body)

    def test_instance_detail_hides_external_fields(self):
        # every UI call site builds its datapoints with skip_external=True since
        # the detail tech view was removed, so an external field has no surface
        # left at all - this is the only assertion on that
        response = self.client.get(reverse("app_data:instance_detail", kwargs={"id": self.obj.id}))
        self.assertNotIn("_f_ext", response.content.decode())

    def test_instance_edit_renders_edit_mode_widgets(self):
        response = self.client.get(reverse("app_data:instance_edit", kwargs={"id": self.obj.id}))
        self.assertEqual(response.status_code, 200)
        body = helper.normalize_html(response.content.decode())
        # edit mode emits its own label + widget per field
        self.assertIn(
            '<label class="col-form-label col-sm-2">F String</label>'
            '<div class="form-check col-sm-10">'
            '<input type="text" class="form-control col-sm-10" '
            'id="f_string" name="f_string" value="plain string value" >',
            body,
        )
        self.assertIn('id="id_f_schema" data-cv-select2="simple"', body)
        self.assertIn('<option value="site01" selected> Site 01 </option>', body)
        # no display-mode markup leaked into the form
        self.assertNotIn("cv-schema-cell-link", body)
        self.assertNotIn("btn btn-outline-success btn-sm", body)

    def test_instance_new_renders_edit_mode_widgets_with_empty_values(self):
        response = self.client.get(
            reverse("app_data:instance_new", kwargs={"classname": helper.FIELDRENDER_CLASSNAME})
        )
        self.assertEqual(response.status_code, 200)
        body = helper.normalize_html(response.content.decode())
        self.assertIn(
            '<input type="text" class="form-control col-sm-10" '
            'id="f_string" name="f_string" value="" >',
            body,
        )
        self.assertIn('id="id_f_schema" data-cv-select2="simple"', body)
        self.assertIn('<option value="site01"> Site 01 </option>', body)

    def test_no_field_is_rendered_through_an_unknown_display_mode(self):
        # guards §4.2 of the plan: a missing/typo'd display_mode must never
        # silently blank a cell once the merged templates branch on it
        urls = [
            reverse("app_data:instance_list", kwargs={"classname": helper.FIELDRENDER_CLASSNAME}),
            reverse("app_data:instance_detail", kwargs={"id": self.obj.id}),
            f"{reverse('app_data:instance_detail', kwargs={'id': self.obj.id})}?print=1",
            reverse("app_data:instance_edit", kwargs={"id": self.obj.id}),
            reverse("app_data:instance_new", kwargs={"classname": helper.FIELDRENDER_CLASSNAME}),
        ]
        for url in urls:
            with self.subTest(url=url):
                response = self.client.get(url)
                self.assertEqual(response.status_code, 200)
                self.assertNotIn("unknown display_mode", response.content.decode())
