"""FT — post.html gear menu (NVM / DEL / BYE).

User-authored Posts grow a #id_gear_btn that opens #id_post_menu with:
    - NVM (everyone)  → navigates to billboard:my_posts
    - DEL (owner)     → hard-deletes the Post
    - BYE (invitee)   → removes the viewer from post.shared_with

Admin-Posts (kind=NOTE_UNLOCK) get the gear menu too but with NVM only —
DEL + BYE don't apply to system-authored threads.

Mirrors apps/gameboard/_partials/_room_gear.html behaviour; see
test_game_room_gatekeeper.py {owner_can_delete_room, gamer_can_abandon_room}
for the room-side analogues.
"""
from selenium.webdriver.common.by import By

from apps.billboard.models import Line, Post
from apps.drama.models import Note
from apps.lyric.models import User

from .base import FunctionalTest


class OwnerPostGearTest(FunctionalTest):
    """Owner of a user-Post sees NVM + DEL in the gear menu; DEL nukes
    the Post and redirects to /billboard/users/<owner.id>/."""

    def setUp(self):
        super().setUp()
        self.owner = User.objects.create(email="owner@test.io")
        self.post = Post.objects.create(
            owner=self.owner, kind=Post.KIND_USER_POST, title="Doomed post",
        )
        Line.objects.create(post=self.post, text="line 1", author=self.owner)
        self.create_pre_authenticated_session("owner@test.io")

    def test_owner_can_delete_post_via_gear_menu(self):
        self.browser.get(
            self.live_server_url + f"/billboard/post/{self.post.id}/"
        )
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
        ).click()
        self.wait_for(
            lambda: self.browser.find_element(
                By.CSS_SELECTOR, "#id_post_menu .btn-danger"
            )
        ).click()
        self.confirm_guard()

        self.wait_for(lambda: self.assertIn(
            f"/billboard/users/{self.owner.id}/", self.browser.current_url
        ))
        self.assertFalse(Post.objects.filter(id=self.post.id).exists())

    def test_gear_menu_for_owner_shows_NVM_and_DEL_but_not_BYE(self):
        self.browser.get(
            self.live_server_url + f"/billboard/post/{self.post.id}/"
        )
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
        ).click()
        menu = self.wait_for(
            lambda: self.browser.find_element(By.ID, "id_post_menu")
        )
        self.assertTrue(menu.find_elements(By.CSS_SELECTOR, ".btn-cancel"))
        self.assertTrue(menu.find_elements(By.CSS_SELECTOR, ".btn-danger"))
        self.assertFalse(menu.find_elements(By.CSS_SELECTOR, ".btn-abandon"))


class InviteePostGearTest(FunctionalTest):
    """Invitee on a user-Post sees NVM + BYE; BYE removes the viewer
    from post.shared_with (owner + other invitees keep the Post)."""

    def setUp(self):
        super().setUp()
        self.owner = User.objects.create(email="owner@test.io")
        self.invitee = User.objects.create(email="invitee@test.io")
        self.other = User.objects.create(email="other@test.io")
        self.post = Post.objects.create(
            owner=self.owner, kind=Post.KIND_USER_POST, title="Shared post",
        )
        Line.objects.create(post=self.post, text="line 1", author=self.owner)
        self.post.shared_with.add(self.invitee, self.other)
        self.create_pre_authenticated_session("invitee@test.io")

    def test_invitee_can_abandon_post_via_gear_menu(self):
        self.browser.get(
            self.live_server_url + f"/billboard/post/{self.post.id}/"
        )
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
        ).click()
        self.wait_for(
            lambda: self.browser.find_element(
                By.CSS_SELECTOR, "#id_post_menu .btn-abandon"
            )
        ).click()
        self.confirm_guard()

        self.wait_for(lambda: self.assertIn(
            f"/billboard/users/{self.invitee.id}/", self.browser.current_url
        ))
        self.post.refresh_from_db()
        self.assertNotIn(self.invitee, self.post.shared_with.all())
        # Post survives — owner + other invitee unaffected
        self.assertEqual(self.post.owner, self.owner)
        self.assertIn(self.other, self.post.shared_with.all())

    def test_gear_menu_for_invitee_shows_NVM_and_BYE_but_not_DEL(self):
        self.browser.get(
            self.live_server_url + f"/billboard/post/{self.post.id}/"
        )
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
        ).click()
        menu = self.wait_for(
            lambda: self.browser.find_element(By.ID, "id_post_menu")
        )
        self.assertTrue(menu.find_elements(By.CSS_SELECTOR, ".btn-cancel"))
        self.assertTrue(menu.find_elements(By.CSS_SELECTOR, ".btn-abandon"))
        self.assertFalse(menu.find_elements(By.CSS_SELECTOR, ".btn-danger"))


class AdminPostGearTest(FunctionalTest):
    """Admin-Post (kind=NOTE_UNLOCK) shows the gear menu with NVM only —
    DEL + BYE don't apply to system-authored threads."""

    def setUp(self):
        super().setUp()
        self.gamer = User.objects.create(email="gamer@test.io")
        Note.grant_if_new(self.gamer, "stargazer")
        self.admin_post = Post.objects.get(
            owner=self.gamer, kind=Post.KIND_NOTE_UNLOCK,
        )
        self.create_pre_authenticated_session("gamer@test.io")

    def test_admin_post_gear_menu_has_NVM_but_no_DEL_no_BYE(self):
        self.browser.get(
            self.live_server_url + f"/billboard/post/{self.admin_post.id}/"
        )
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
        ).click()
        menu = self.wait_for(
            lambda: self.browser.find_element(By.ID, "id_post_menu")
        )
        self.assertTrue(menu.find_elements(By.CSS_SELECTOR, ".btn-cancel"))
        self.assertFalse(menu.find_elements(By.CSS_SELECTOR, ".btn-danger"))
        self.assertFalse(menu.find_elements(By.CSS_SELECTOR, ".btn-abandon"))
