from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

from .base import FunctionalTest
from apps.applets.models import Applet


class DashboardMaintenanceTest(FunctionalTest):
    def setUp(self):
        super().setUp()
        Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
        Applet.objects.get_or_create(slug="palette", defaults={"name": "Palette"})
        
    def test_user_without_username_can_claim_unclaimed_username(self):
        # 1. Create a pre-authenticated session for discoman@example.com
        self.create_pre_authenticated_session("discoman@example.com")
        # 2. Navigate to self.live_server_url + "/"
        self.browser.get(self.live_server_url)
        # 3. Find the username applet on the page; look for a <section> or <div> with id="id_username_applet"
        self.browser.find_element(By.ID, "id_applet_username")
        # 5. Find the username input field inside the applet & type a username
        username_input = self.browser.find_element(By.CSS_SELECTOR, "#id_new_username")
        # 4. Assert it shows the current display name (truncated email: di…an@e…e.com) NOPE the username value itself now
        self.assertEqual("", username_input.get_attribute("value"))
        # 6. Type a username, e.g., discoman
        username_input.send_keys("discoman")
        self.wait_for(
            lambda: self.browser.find_element(By.CSS_SELECTOR, "#id_new_username:valid")
        )
        # 7. Submit the form (click a btn or press Enter)
        username_input.send_keys(Keys.ENTER)
        # 8. Without a page reload, wait for the navbar to update; user wait_for() to check that the navbar text now contains "discoman"
        self.wait_for(
            lambda: self.assertIn(
                "discoman",
                self.browser.find_element(By.CLASS_NAME, "navbar-text").text
            )
        )
        # 9. Also assert the applet input now shows "discoman" as its value
        self.wait_for(
            lambda: self.assertEqual(
                "discoman",
                self.browser.find_element(By.CSS_SELECTOR, "#id_new_username").get_attribute("value")
            )
        )

    def test_user_can_toggle_applet_visibility_via_gear_menu(self):
        # 1. Auth as discoman@example.com, navigate home
        self.create_pre_authenticated_session("discoman@example.com")
        self.browser.get(self.live_server_url)
        # 2. Assert both applets present on page (id_applet_username, id_applet_palette)
        self.browser.find_element(By.ID, "id_applet_username")
        self.browser.find_element(By.ID, "id_applet_palette")
        # 3. Click el w. id="id_dash_gear"
        dash_gear = self.browser.find_element(By.CSS_SELECTOR, ".gear-btn")
        dash_gear.click()
        # 4. A menu appears; wait_for el w. id="id_dash_applet_menu"
        self.wait_for(
            lambda: self.assertTrue(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )
        # 5. Find two checkboxes in menu, name="username" & name="palette"; assert both .is_selected()
        menu = self.browser.find_element(By.ID, "id_dash_applet_menu")
        username_cb = menu.find_element(By.CSS_SELECTOR, '[name="applets"][value="username"]')
        palette_cb = menu.find_element(By.CSS_SELECTOR, '[name="applets"][value="palette"]')
        self.assertTrue(username_cb.is_selected())
        self.assertTrue(palette_cb.is_selected())
        # 6. Click palette box to uncheck it
        palette_cb.click()
        self.assertFalse(palette_cb.is_selected())
        self.browser.execute_script("window.__no_reload_marker = true")
        # 7. Submit the menu form via [type="submit"] btn inside menu
        menu.find_element(By.CSS_SELECTOR, '[type="submit"]').click()
        self.wait_for(
            lambda: self.assertFalse(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )
        # 8. wait_for palette applet to be gone
        self.wait_for(
            lambda: self.assertRaises(
                NoSuchElementException,
                self.browser.find_element,
                By.ID, "id_applet_palette"
            )
        )
        # 9. assert id_applet_username remains
        self.browser.find_element(By.ID, "id_applet_username")
        # 10. Click gear again, find menu, find palette checkbox; assert now NOT selected
        dash_gear.click()
        self.wait_for(
            lambda: self.assertTrue(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )
        menu = self.browser.find_element(By.ID, "id_dash_applet_menu")
        palette_cb = menu.find_element(By.CSS_SELECTOR, '[name="applets"][value="palette"]')
        self.assertFalse(palette_cb.is_selected())
        # 11. Click it to re-check box; submit
        palette_cb.click()
        self.assertTrue(palette_cb.is_selected())
        menu.find_element(By.CSS_SELECTOR, '[type="submit"]').click()
        # 12. wait_for id_applet_palette to reappear
        self.wait_for(
            lambda: self.assertFalse(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )
        self.wait_for(
            lambda: self.assertTrue(
                self.browser.find_element(By.ID, "id_applet_palette")
            )
        )
        self.assertTrue(self.browser.execute_script("return window.__no_reload_marker === true"))

class AppletMenuDismissTest(FunctionalTest):
    def setUp(self):
        super().setUp()
        # Portrait viewport: sidebars don't activate, h2 sits safely above
        # #id_dash_content and can't be obscured by it regardless of font metrics.
        self.browser.set_window_size(800, 1200)
        Applet.objects.get_or_create(slug="username", defaults={"name": "Username"})
        Applet.objects.get_or_create(slug="palette", defaults={"name": "Palette"})
        self.create_pre_authenticated_session("discoman@example.com")
        self.browser.get(self.live_server_url)

    def _open_menu(self):
        self.browser.find_element(By.CSS_SELECTOR, ".gear-btn").click()
        self.wait_for(
            lambda: self.assertTrue(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )

    def test_gear_click_toggles_menu_closed(self):
        self._open_menu()
        self.browser.find_element(By.CSS_SELECTOR, ".gear-btn").click()
        self.wait_for(
            lambda: self.assertFalse(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )

    def test_nvm_btn_closes_menu(self):
        self._open_menu()
        self.browser.find_element(By.ID, "id_applet_menu_cancel").click()
        self.wait_for(
            lambda: self.assertFalse(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )

    def test_click_outside_closes_menu(self):
        self._open_menu()
        self.browser.find_element(By.TAG_NAME, "h2").click()
        self.wait_for(
            lambda: self.assertFalse(
                self.browser.find_element(By.ID, "id_dash_applet_menu").is_displayed()
            )
        )
