"""The uniform board card: 1/3 portrait, 2/3 text, no placeholders.

Every member gets the same card — nobody is featured. A photo takes the left
third, whole and matted; a member without one gets the full width for text,
and never an initials circle or any other stand-in.
"""
import shutil
import tempfile

from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase, override_settings
from django.urls import reverse

from documents.models import BoardMember

User = get_user_model()
_TMP = tempfile.mkdtemp(prefix="hartling-boardcard-test-")

PNG = (b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01"
       b"\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDATx\x9cc\xf8\xcf\xc0"
       b"\x00\x00\x00\x03\x00\x01\x9a\x92\xdc\xef\x00\x00\x00\x00IEND\xaeB`\x82")


@override_settings(PRIVATE_MEDIA_ROOT=_TMP)
class BoardCardTests(TestCase):
    @classmethod
    def tearDownClass(cls):
        shutil.rmtree(_TMP, ignore_errors=True)
        super().tearDownClass()

    def setUp(self):
        self.owner = User.objects.create_user("owner", password="pw-owner-12345")
        self.with_photo = BoardMember.objects.create(
            name="Pat Chair", title="Chair", active=True, order=1,
            bio="First paragraph of a long biography.\n\nSecond paragraph.",
            photo=SimpleUploadedFile("pat.png", PNG, content_type="image/png"),
        )
        self.without_photo = BoardMember.objects.create(
            name="Lee Director", title="Director", active=True, order=2,
            bio="<p>Edited in the staff dialog, so already <strong>HTML</strong>.</p>",
        )
        self.client.force_login(self.owner)
        self.body = self.client.get(reverse("documents:board"), secure=True).content.decode()

    def card_of(self, name):
        start = self.body.index(name)
        left = self.body.rindex('<li class="member-card', 0, start)
        return self.body[left:self.body.index("</li>", start)]

    def test_a_photo_member_gets_the_split_card(self):
        card = self.card_of("Pat Chair")
        self.assertIn("member-card has-photo", card)
        self.assertIn("member-stage", card)
        self.assertIn('alt="Portrait of Pat Chair"', card)

    def test_a_photoless_member_gets_full_width_text_and_no_stand_in(self):
        card = self.card_of("Lee Director")
        self.assertNotIn("has-photo", card)
        self.assertNotIn("member-stage", card)
        self.assertNotIn("member-initials", card)
        self.assertNotIn("<img", card)

    def test_the_board_grid_never_shows_an_initials_placeholder(self):
        grid = self.body[self.body.index('id="board-grid"'):self.body.index("</ul>")]
        self.assertNotIn("member-initials", grid)

    def test_every_bio_carries_the_inline_toggle(self):
        for name in ("Pat Chair", "Lee Director"):
            card = self.card_of(name)
            self.assertIn("bio-toggle", card, name)
            self.assertIn("Read the full profile", card)

    def test_nobody_is_featured_larger(self):
        """All members render through the one card template."""
        self.assertEqual(self.body.count('<li class="member-card'), 2)

    # ---- bio_html handles both storage formats ----
    def test_plain_imported_text_becomes_paragraphs(self):
        html = str(self.with_photo.bio_html)
        self.assertEqual(html.count("<p>"), 2)
        self.assertIn("Second paragraph.", html)

    def test_editor_html_passes_through_untouched(self):
        self.assertIn("<strong>HTML</strong>", str(self.without_photo.bio_html))

    def test_plain_text_is_escaped_on_the_way_in(self):
        member = BoardMember(bio="A <script>alert(1)</script> plain bio.")
        self.assertNotIn("<script>", str(member.bio_html))


class BoardMatteTextureTests(TestCase):
    def test_the_portrait_matte_carries_the_library_texture(self):
        """The stage behind a portrait uses the same per-property texture as
        the document library's browse panel — one visual language."""
        from django.conf import settings
        css = (settings.BASE_DIR / "static" / "portal.css").read_text()
        stage = css[css.rindex(".member-stage {"):]
        stage = stage[:stage.index("}")]
        self.assertIn("var(--rail-image", stage)
        self.assertIn("background-blend-mode: multiply", stage)
