"""FT for the My Buds page — line rendering w. donned title + click-lock
tooltip portal + username <a> link to the per-bud landing page.

Companion to test_bill_my_buds.py (which covers Phase 1 add/render).
This file covers the My Buds enrichment that lands alongside the new
apps/billboard/bud.html landing page (see test_bill_bud_page.py).

Spec recap:
- Each bud row reads `@<handle> the <Title>` (at_handle + active_title_display).
- Clicking the row applies `.row-locked` to the `li.applet-list-entry` AND
  opens the shared #id_tooltip_portal w. five fields:
      .tt-title       → `@<handle>`
      .tt-description → bud's donned title  ("Earthman" by default)
      .tt-email       → bud's email (small / italic / 0.75 opacity — CSS)
      .tt-shoptalk    → the user's personal note about this bud (160-char cap)
      .tt-milestone   → "edited <relative-ts>"  (omitted when no edit yet)
- The `@<handle>` itself is an `<a>` element (--terUser by CSS) whose href
  navigates to the bud's landing page /billboard/buds/<bud_id>/.
"""
from selenium.webdriver.common.by import By

from apps.lyric.models import User

from .base import FunctionalTest


class MyBudsLineRendersBudTitleTest(FunctionalTest):
    def setUp(self):
        super().setUp()
        self.gamer = User.objects.create(email="me@test.io", username="me")
        self.alice = User.objects.create(email="alice@test.io", username="alice")
        self.gamer.buds.add(self.alice)
        self.create_pre_authenticated_session("me@test.io")

    def test_bud_entry_reads_at_handle_the_title(self):
        """Default (no donned Note) → '@alice the Earthman' — active_title_display
        falls back to 'Earthman' when the bud hasn't donned any Note title.
        Renders inside .bud-entry; the username span carries the `.bud-name`
        class for backward compat w. test_bill_my_buds.py."""
        self.browser.get(self.live_server_url + "/billboard/my-buds/")
        entry = self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR, f".bud-entry[data-bud-id='{self.alice.id}']"
        ))
        # Full row text combines handle + title
        self.assertIn("@alice the Earthman", entry.text)


class MyBudsClickOpensTooltipPortalTest(FunctionalTest):
    def setUp(self):
        super().setUp()
        self.gamer = User.objects.create(email="me@test.io", username="me")
        self.alice = User.objects.create(email="alice@test.io", username="alice")
        self.gamer.buds.add(self.alice)
        self.create_pre_authenticated_session("me@test.io")

    def test_click_locks_row_and_opens_tooltip_portal(self):
        """Click the bud row → li picks up .row-locked AND the shared
        #id_tooltip_portal becomes .active w. the bud's data populated
        into .tt-title / .tt-description / .tt-email."""
        self.browser.get(self.live_server_url + "/billboard/my-buds/")
        row = self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR, f".bud-entry[data-bud-id='{self.alice.id}']"
        ))
        self.assertNotIn("row-locked", row.get_attribute("class") or "")

        row.click()

        # Row picks up .row-locked
        self.wait_for(lambda: self.assertIn(
            "row-locked", row.get_attribute("class") or ""
        ))

        # Portal slides in active
        portal = self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR, "#id_tooltip_portal.active"
        ))
        # Field assertions — text() suffices; the SCSS rules (italic,
        # opacity, glow) are out of FT scope.
        title = portal.find_element(By.CSS_SELECTOR, ".tt-title").text
        desc  = portal.find_element(By.CSS_SELECTOR, ".tt-description").text
        email = portal.find_element(By.CSS_SELECTOR, ".tt-email").text
        self.assertEqual(title, "@alice")
        self.assertEqual(desc,  "Earthman")
        self.assertEqual(email, "alice@test.io")

    def test_tooltip_milestone_absent_when_shoptalk_never_edited(self):
        """`.tt-milestone` renders only when the user has edited the shoptalk
        for this bud — fresh bud has no BudshipNote row yet, so no edit
        timestamp exists. The cell should be ABSENT (not empty)."""
        self.browser.get(self.live_server_url + "/billboard/my-buds/")
        row = self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR, f".bud-entry[data-bud-id='{self.alice.id}']"
        ))
        row.click()
        self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR, "#id_tooltip_portal.active"
        ))
        self.assertEqual(
            self.browser.find_elements(By.CSS_SELECTOR, "#id_tooltip_portal .tt-milestone"),
            [],
        )

    def test_tooltip_shoptalk_empty_string_when_never_edited(self):
        """Shoptalk slot still renders (so the layout slot exists), just
        with empty body. Distinguishes never-edited (slot empty) from
        cleared-after-edit (slot empty + .tt-milestone present)."""
        self.browser.get(self.live_server_url + "/billboard/my-buds/")
        self.browser.find_element(
            By.CSS_SELECTOR, f".bud-entry[data-bud-id='{self.alice.id}']"
        ).click()
        portal = self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR, "#id_tooltip_portal.active"
        ))
        # .tt-shoptalk exists but is empty
        shoptalk = portal.find_element(By.CSS_SELECTOR, ".tt-shoptalk")
        self.assertEqual(shoptalk.text.strip(), "")


class MyBudsUsernameAnchorTest(FunctionalTest):
    def setUp(self):
        super().setUp()
        self.gamer = User.objects.create(email="me@test.io", username="me")
        self.alice = User.objects.create(email="alice@test.io", username="alice")
        self.gamer.buds.add(self.alice)
        self.create_pre_authenticated_session("me@test.io")

    def test_username_inside_row_is_anchor_to_bud_page(self):
        """The `@alice` text itself is wrapped in an `<a>` element (--terUser
        per global SCSS); href routes to /billboard/buds/<bud_id>/. The row
        wrapper still receives clicks for the row-lock + tooltip flow (the
        anchor is a CHILD of the bud-name span; clicking the row outside
        the anchor locks; clicking the anchor itself navigates)."""
        self.browser.get(self.live_server_url + "/billboard/my-buds/")
        anchor = self.wait_for(lambda: self.browser.find_element(
            By.CSS_SELECTOR,
            f".bud-entry[data-bud-id='{self.alice.id}'] .bud-name a",
        ))
        self.assertEqual(anchor.text, "@alice")
        href = anchor.get_attribute("href")
        self.assertIn(f"/billboard/buds/{self.alice.id}/", href)
