"""
Functional tests: deck-to-seat contribution mechanics.

Sprint 1 (DeckContributionTest):
  Confirming a role in ROLE SELECT assigns the gamer's equipped deck to the
  TableSeat.  The Game Kit immediately reflects the in-use state: the deck
  card gains the game name in its tooltip and the micro-status reads "In-Use".

Sprint 2 (DeckInUseGameKitTest):
  With a deck already assigned to an active seat the Game Kit DON button is
  btn-disabled and no DOFF toggle is shown (unlike the normal equipped state
  where DOFF is visible).  Clicking the card shows a tooltip naming the game.
  A second deck that is NOT assigned to any active seat has normal DON/DOFF
  behaviour.
"""
import time

from django.test import tag
from selenium.webdriver.common.by import By

from apps.applets.models import Applet
from apps.epic.models import DeckVariant, GateSlot, Room, TableSeat
from apps.lyric.models import User
from functional_tests.base import FunctionalTest
from functional_tests.room_page import _fill_room_via_orm

FOUNDER_EMAIL  = "founder@test.io"
GAMER_EMAIL    = "gamer@test.io"


def _equip_earthman(user):
    earthman, _ = DeckVariant.objects.get_or_create(
        slug="earthman",
        defaults={"name": "Earthman", "card_count": 106, "is_default": True},
    )
    user.equipped_deck = earthman
    user.save(update_fields=["equipped_deck"])
    # Signal may not have added this (earthman didn't exist when the user was created)
    user.unlocked_decks.add(earthman)
    return earthman


def _room_at_role_select(name="Wildfire"):
    """Create a room filled to 6 and at ROLE_SELECT table status."""
    founder, _ = User.objects.get_or_create(email=FOUNDER_EMAIL)
    room = Room.objects.create(name=name, owner=founder)
    emails = [FOUNDER_EMAIL, GAMER_EMAIL,
              "b@test.io", "c@test.io", "d@test.io", "e@test.io"]
    _fill_room_via_orm(room, emails)
    for slot in room.gate_slots.all():
        if slot.gamer:
            _equip_earthman(slot.gamer)
    room.table_status = Room.ROLE_SELECT
    room.save()
    return room, founder


# ── Sprint 1 ─────────────────────────────────────────────────────────────────

class DeckContributionTest(FunctionalTest):
    """Sprint 1: role confirmation → TableSeat.deck_variant set; Game Kit shows In-Use."""

    def setUp(self):
        super().setUp()
        self.browser.set_window_size(800, 1200)
        for slug, name, ctx in [
            ("game-kit",  "Game Kit",  "gameboard"),
            ("gk-decks",  "Card Decks","game-kit"),
        ]:
            Applet.objects.get_or_create(slug=slug, defaults={"name": name, "context": ctx})

    def test_confirming_role_assigns_equipped_deck_to_seat(self):
        """After the gamer confirms a role, Game Kit shows the Earthman deck as 'In-Use'
        with the game name in the deck tooltip, and the micro-status changes from
        'Equipped' to 'In-Use'.
        """
        room, founder = _room_at_role_select()
        gamer = User.objects.get(email=GAMER_EMAIL)
        # Create TableSeats; pre-assign slot 1 (PC) so gamer (slot 2) is the active seat
        for slot in room.gate_slots.order_by("slot_number"):
            role = "PC" if slot.slot_number == 1 else None
            TableSeat.objects.create(
                room=room, gamer=slot.gamer, slot_number=slot.slot_number, role=role
            )

        # Gamer logs in and navigates to the role-select room
        self.create_pre_authenticated_session(GAMER_EMAIL)
        self.browser.get(self.live_server_url + f"/gameboard/room/{room.pk}/")

        # Gamer is slot 2 — card stack is eligible because slot 1/PC is pre-assigned
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, ".card-stack[data-state='eligible']")
        ).click()
        self.wait_for(lambda: self.browser.find_element(By.ID, "id_role_select"))
        self.browser.find_element(By.CSS_SELECTOR, "#id_role_select .card").click()
        self.confirm_guard()

        # Deck is now assigned to the seat in the DB
        self.wait_for(lambda: self.assertTrue(
            TableSeat.objects.filter(
                gamer=gamer,
                room=room,
                deck_variant=gamer.equipped_deck,
            ).exists(),
            "TableSeat.deck_variant was not set after role confirmation",
        ))

        # Navigate to Game Kit — earthman deck renders directly (in-use, no placeholder click needed)
        self.browser.get(self.live_server_url + "/gameboard/")
        earthman_card = self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_earthman_deck")
        )
        # Game name lives on data-in-use-room-name; the mini-portal renders it as
        # "In-Use: <name>" on hover (Jasmine covers the JS truncation).
        self.assertEqual(
            room.name, earthman_card.get_attribute("data-in-use-room-name")
        )


# ── Sprint 2 ─────────────────────────────────────────────────────────────────

class DeckInUseGameKitTest(FunctionalTest):
    """Sprint 2: DON disabled + no DOFF toggle for in-use deck; second deck unaffected."""

    def setUp(self):
        super().setUp()
        self.browser.set_window_size(800, 1200)
        for slug, name, ctx in [
            ("game-kit",  "Game Kit",  "gameboard"),
            ("gk-decks",  "Card Decks","game-kit"),
        ]:
            Applet.objects.get_or_create(slug=slug, defaults={"name": name, "context": ctx})

    def _setup_in_use_deck(self):
        """Create a seated gamer whose Earthman deck is already assigned to a seat."""
        room, founder = _room_at_role_select()
        gamer = User.objects.get(email=GAMER_EMAIL)
        earthman = _equip_earthman(gamer)
        # Assign deck directly (Sprint 1 must be green first)
        seat = TableSeat.objects.create(
            gamer=gamer, room=room, slot_number=2, role="NC", deck_variant=earthman
        )
        return gamer, earthman, room, seat

    def test_don_is_disabled_and_doff_absent_for_in_use_deck(self):
        """DON button carries btn-disabled; DOFF is not rendered at all (not just disabled)."""
        gamer, earthman, room, seat = self._setup_in_use_deck()
        self.create_pre_authenticated_session(GAMER_EMAIL)
        self.browser.get(self.live_server_url + "/gameboard/")
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_earthman_deck")
        ).click()

        # DON is disabled
        don_btn = self.wait_for(
            lambda: self.browser.find_element(
                By.CSS_SELECTOR, f"#id_kit_earthman_deck .btn-equip"
            )
        )
        self.assertIn("btn-disabled", don_btn.get_attribute("class"))

        # DOFF is present but disabled (both buttons disabled for in-use deck)
        doff_btn = self.wait_for(
            lambda: self.browser.find_element(
                By.CSS_SELECTOR, f"#id_kit_earthman_deck .btn-unequip"
            )
        )
        self.assertIn("btn-disabled", doff_btn.get_attribute("class"),
                      "DOFF should be present but disabled for an in-use deck")

    def test_in_use_deck_carries_game_name_for_mini_portal(self):
        """The in-use deck token exposes the room name via data-in-use-room-name
        so the mini-portal can render it as 'In-Use: <name>' on hover."""
        gamer, earthman, room, seat = self._setup_in_use_deck()
        self.create_pre_authenticated_session(GAMER_EMAIL)
        self.browser.get(self.live_server_url + "/gameboard/")
        deck_el = self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_earthman_deck")
        )
        self.assertEqual(room.name, deck_el.get_attribute("data-in-use-room-name"))

    def test_non_contributing_deck_has_normal_don_doff(self):
        """A deck not assigned to any active seat shows the normal DON/DOFF apparatus."""
        gamer, earthman, room, seat = self._setup_in_use_deck()
        # Unlock RWS for the gamer so it appears in Game Kit
        rws, _ = DeckVariant.objects.get_or_create(
            slug="tarot-rider-waite-smith",
            defaults={"name": "Tarot (Rider-Waite-Smith)", "card_count": 78},
        )
        gamer.unlocked_decks.add(rws)
        self.create_pre_authenticated_session(GAMER_EMAIL)
        self.browser.get(self.live_server_url + "/gameboard/")
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_kit_tarot_deck")
        ).click()
        don_btn = self.wait_for(
            lambda: self.browser.find_element(
                By.CSS_SELECTOR, "#id_kit_tarot_deck .btn-equip"
            )
        )
        self.assertNotIn("btn-disabled", don_btn.get_attribute("class"))
