# -*- coding: utf-8 -*-
"""Users page object for User Management features in the admin UI.

Location: ./tests/playwright/pages/users_page.py
Copyright 2026
SPDX-License-Identifier: Apache-2.0
Authors: Marek Dano
"""

# Third-Party
from playwright.sync_api import Locator
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
from playwright.sync_api import expect as pw_expect

# Local
from .base_page import BasePage


class UsersPage(BasePage):
    """Page object for User Management features.

    This page manages the Users tab where admins can:
    - View and search users
    - Create new users
    - Edit user details (full name, admin status, password)
    - Activate/deactivate users
    - Force password change
    - Delete users
    """

    # ==================== Panel Elements ====================

    @property
    def users_panel(self) -> Locator:
        """Users panel container."""
        return self.page.locator("#users-panel")

    # ==================== Create User Form Elements ====================

    @property
    def create_user_form(self) -> Locator:
        """Create user form."""
        return self.page.locator("#create-user-form")

    @property
    def user_email_input(self) -> Locator:
        """Email input field."""
        return self.create_user_form.locator('input[name="email"]')

    @property
    def user_full_name_input(self) -> Locator:
        """Full name input field."""
        return self.create_user_form.locator('input[name="full_name"]')

    @property
    def user_password_input(self) -> Locator:
        """Password input field."""
        return self.create_user_form.locator("#new_user_password")

    @property
    def user_is_admin_checkbox(self) -> Locator:
        """Is admin checkbox."""
        return self.create_user_form.locator("#is_admin")

    @property
    def create_user_submit_btn(self) -> Locator:
        """Create user submit button."""
        return self.create_user_form.locator("#create_user_submit")

    @property
    def user_creation_messages(self) -> Locator:
        """User creation messages container."""
        return self.page.locator("#user-creation-messages")

    # ==================== Users List Elements ====================

    @property
    def users_list_container(self) -> Locator:
        """Users list container (loaded via HTMX)."""
        return self.page.locator("#users-list-container")

    @property
    def user_cards(self) -> Locator:
        """All user cards in the list."""
        return self.page.locator(".user-card")

    # ==================== Edit Modal Elements ====================

    @property
    def user_edit_modal(self) -> Locator:
        """User edit modal overlay."""
        return self.page.locator("#user-edit-modal")

    @property
    def user_edit_modal_content(self) -> Locator:
        """User edit modal content container."""
        return self.page.locator("#user-edit-modal-content")

    # ==================== Navigation ====================

    def navigate_to_users_tab(self) -> None:
        """Navigate to Users tab and wait for the user list to finish loading."""
        self.sidebar.click_users_tab()
        self.wait_for_users_loaded()

    # ==================== User Creation ====================

    def create_user(self, email: str, full_name: str, password: str, is_admin: bool = False) -> None:
        """Create a new user by filling and submitting the form.

        Args:
            email: User email address
            full_name: User full name
            password: User password
            is_admin: Whether to grant admin privileges
        """
        self.fill_locator(self.user_email_input, email)
        self.fill_locator(self.user_full_name_input, full_name)
        self.fill_locator(self.user_password_input, password)
        if is_admin:
            if not self.user_is_admin_checkbox.is_checked():
                self.click_locator(self.user_is_admin_checkbox)
        # Wait for password validation JS to enable submit button
        pw_expect(self.create_user_submit_btn).to_be_enabled(timeout=5000)
        self.click_locator(self.create_user_submit_btn)

    # ==================== User List Operations ====================

    def wait_for_users_loaded(self, timeout: int = 30000) -> None:
        """Wait for the users list to load via HTMX.

        Args:
            timeout: Maximum time to wait in milliseconds
        """
        self.page.wait_for_selector("#users-panel:not(.hidden)", timeout=timeout)
        self.wait_for_attached(self.users_list_container, timeout=timeout)
        # Wait for HTMX loading to complete
        try:
            self.page.wait_for_function(
                "() => !document.querySelector('#users-loading.htmx-request')",
                timeout=timeout,
            )
        except PlaywrightTimeoutError:
            pass

    def find_user_card(self, email: str) -> Locator:
        """Locate a user card by email text.

        Args:
            email: User email to search for

        Returns:
            Locator for the user card containing the email
        """
        return self.page.locator(f".user-card:has-text('{email}')")

    def user_exists_in_list(self, email: str) -> bool:
        """Check if a user with the given email exists in the user list.

        Args:
            email: User email to check

        Returns:
            True if user is visible in the list
        """
        return self.find_user_card(email).count() > 0

    def wait_for_user_visible(self, email: str, timeout: int = 30000) -> None:
        """Wait for a user to appear in the list.

        Args:
            email: User email to wait for
            timeout: Maximum time to wait in milliseconds
        """
        self.page.wait_for_selector(f".user-card:has-text('{email}')", timeout=timeout)

    def reload_and_navigate_to_users(self) -> None:
        """Reload the page so the users list is refreshed.

        Waits for any in-flight HTMX requests to settle before reloading,
        then loads admin directly on the users hash to force a fresh
        users-partial fetch.
        """
        try:
            self.page.wait_for_function(
                "() => !document.querySelector('.htmx-request')",
                timeout=10000,
            )
        except PlaywrightTimeoutError:
            pass  # Proceed with reload even if HTMX requests are still pending
        self.page.wait_for_load_state("domcontentloaded")
        self.page.goto("/admin#users", wait_until="domcontentloaded")
        self.wait_for_users_loaded()

    def user_has_badge(self, email: str, badge_text: str) -> bool:
        """Check if a user card has a specific badge.

        Args:
            email: User email to check
            badge_text: Badge text to look for (e.g., "Active", "Inactive", "Admin")

        Returns:
            True if the badge is present on the user card
        """
        card = self.find_user_card(email)
        return card.get_by_text(badge_text, exact=True).count() > 0

    # ==================== User Card Actions ====================

    def click_edit_button(self, email: str) -> None:
        """Click the Edit button on a user card and wait for the modal.

        Args:
            email: User email to edit
        """
        card = self.find_user_card(email)
        card.locator("button:has-text('Edit')").click()
        # Wait for the modal to become visible and content to load
        self.page.wait_for_selector("#user-edit-modal:not(.hidden)", timeout=10000)
        self.page.wait_for_selector("#user-edit-modal-content form", timeout=10000)

    def submit_edit_form(self, full_name: str | None = None, password: str | None = None, confirm_password: str | None = None, is_admin: bool | None = None) -> None:
        """Fill and submit the user edit modal form.

        Args:
            full_name: New full name (None to leave unchanged)
            password: New password (None to leave unchanged)
            confirm_password: Password confirmation (None to leave unchanged)
            is_admin: Admin status (None to leave unchanged)
        """
        modal_content = self.user_edit_modal_content
        if full_name is not None:
            name_input = modal_content.locator('input[name="full_name"]')
            name_input.fill(full_name)
        if is_admin is not None:
            admin_checkbox = modal_content.locator('input[name="is_admin"]')
            is_checked = admin_checkbox.is_checked()
            if is_admin and not is_checked:
                admin_checkbox.click()
            elif not is_admin and is_checked:
                admin_checkbox.click()
        if password is not None:
            pwd_input = modal_content.locator('input[name="password"]')
            pwd_input.fill(password)
        if confirm_password is not None:
            confirm_input = modal_content.locator('input[name="confirm_password"]')
            confirm_input.fill(confirm_password)
        # Submit the form
        modal_content.locator('button[type="submit"]').click()

    def close_edit_modal(self) -> None:
        """Close the user edit modal."""
        self.page.evaluate("""
            const modal = document.getElementById('user-edit-modal');
            if (modal) {
                modal.style.display = 'none';
                modal.classList.add('hidden');
            }
        """)

    def _click_action_with_confirm(self, email: str, button_text: str) -> None:
        """Click an action button on a user card that triggers an hx-confirm dialog.

        Sets up a dialog handler to accept the native confirm() dialog
        before clicking the button.

        Args:
            email: User email to act on
            button_text: Button text to click (e.g., "Activate", "Deactivate", "Delete")
        """
        card = self.find_user_card(email)
        # Accept the native confirm dialog triggered by hx-confirm
        self.page.once("dialog", lambda dialog: dialog.accept())
        card.locator(f"button:has-text('{button_text}')").click()

    def click_activate(self, email: str) -> None:
        """Click the Activate button on a user card (accepts confirm dialog).

        Args:
            email: User email to activate
        """
        self._click_action_with_confirm(email, "Activate")

    def click_deactivate(self, email: str) -> None:
        """Click the Deactivate button on a user card (accepts confirm dialog).

        Args:
            email: User email to deactivate
        """
        self._click_action_with_confirm(email, "Deactivate")

    def click_delete(self, email: str) -> None:
        """Click the Delete button on a user card (accepts confirm dialog).

        Args:
            email: User email to delete
        """
        self._click_action_with_confirm(email, "Delete")

    def click_force_password_change(self, email: str) -> None:
        """Click the Force Password Change button on a user card (accepts confirm dialog).

        Args:
            email: User email to force password change
        """
        self._click_action_with_confirm(email, "Force Password Change")

    def click_unlock(self, email: str) -> None:
        """Click the Unlock button on a user card (accepts confirm dialog).

        Args:
            email: User email to unlock
        """
        self._click_action_with_confirm(email, "Unlock")
