"""
E2E tests for user registration and authentication flows.

These tests verify the complete user journey for registration,
login, and account management using Playwright for browser automation.
"""

import pytest
from playwright.sync_api import Page, expect


@pytest.mark.e2e
class TestUserRegistration:
    """E2E tests for user registration flow."""

    def test__registration_page__displays_form(self, page: Page, live_server):
        """Test registration page displays the registration form."""
        page.goto(f"{live_server.url}/accounts/signup/")

        # Verify form fields are visible
        expect(page.get_by_label("Username")).to_be_visible()
        expect(page.get_by_label("Email")).to_be_visible()
        expect(page.get_by_label("Password", exact=False).first).to_be_visible()

    def test__registration__valid_data__creates_account(self, page: Page, live_server):
        """Test registration with valid data creates an account."""
        page.goto(f"{live_server.url}/accounts/signup/")

        # Fill registration form
        page.get_by_label("Username").fill("e2e_newuser")
        page.get_by_label("Email").fill("e2e_newuser@example.com")

        # Handle password fields (may be "Password" and "Confirm Password" or similar)
        password_fields = page.locator("input[type='password']")
        if password_fields.count() >= 2:
            password_fields.nth(0).fill("SecurePass123!")
            password_fields.nth(1).fill("SecurePass123!")
        else:
            password_fields.first.fill("SecurePass123!")

        # Submit form
        page.get_by_role("button", name="Sign Up").click()

        # Should redirect to success page or login
        page.wait_for_url("**/*", timeout=5000)

    def test__registration__duplicate_username__shows_error(self, page: Page, live_server, regular_user):
        """Test registration with duplicate username shows error."""
        page.goto(f"{live_server.url}/accounts/signup/")

        # Try to register with existing username
        page.get_by_label("Username").fill("testuser")
        page.get_by_label("Email").fill("different@example.com")

        password_fields = page.locator("input[type='password']")
        if password_fields.count() >= 2:
            password_fields.nth(0).fill("SecurePass123!")
            password_fields.nth(1).fill("SecurePass123!")
        else:
            password_fields.first.fill("SecurePass123!")

        page.get_by_role("button", name="Sign Up").click()

        # Should show error message
        error = page.locator(".error, .errorlist, [role='alert']")
        expect(error.first).to_be_visible()

    def test__registration__weak_password__shows_error(self, page: Page, live_server):
        """Test registration with weak password shows validation error."""
        page.goto(f"{live_server.url}/accounts/signup/")

        page.get_by_label("Username").fill("e2e_weakpass")
        page.get_by_label("Email").fill("e2e_weakpass@example.com")

        password_fields = page.locator("input[type='password']")
        if password_fields.count() >= 2:
            password_fields.nth(0).fill("123")
            password_fields.nth(1).fill("123")
        else:
            password_fields.first.fill("123")

        page.get_by_role("button", name="Sign Up").click()

        # Should show password validation error
        error = page.locator(".error, .errorlist, [role='alert']")
        expect(error.first).to_be_visible()


@pytest.mark.e2e
class TestUserLogin:
    """E2E tests for user login flow."""

    def test__login_page__displays_form(self, page: Page, live_server):
        """Test login page displays the login form."""
        page.goto(f"{live_server.url}/accounts/login/")

        expect(page.get_by_label("Username")).to_be_visible()
        expect(page.get_by_label("Password")).to_be_visible()
        expect(page.get_by_role("button", name="Sign In")).to_be_visible()

    def test__login__valid_credentials__authenticates(self, page: Page, live_server, regular_user):
        """Test login with valid credentials authenticates user."""
        page.goto(f"{live_server.url}/accounts/login/")

        page.get_by_label("Username").fill("testuser")
        page.get_by_label("Password").fill("testpass123")
        page.get_by_role("button", name="Sign In").click()

        # Should redirect away from login page
        page.wait_for_url("**/*")
        expect(page).not_to_have_url("**/login/**")

    def test__login__invalid_credentials__shows_error(self, page: Page, live_server):
        """Test login with invalid credentials shows error."""
        page.goto(f"{live_server.url}/accounts/login/")

        page.get_by_label("Username").fill("nonexistent")
        page.get_by_label("Password").fill("wrongpass")
        page.get_by_role("button", name="Sign In").click()

        # Should show error message
        error = page.locator(".error, .errorlist, [role='alert'], .alert-danger")
        expect(error.first).to_be_visible()

    def test__login__remember_me__checkbox_present(self, page: Page, live_server):
        """Test login page has remember me checkbox."""
        page.goto(f"{live_server.url}/accounts/login/")

        remember_me = page.locator("input[name='remember'], input[type='checkbox'][id*='remember']")

        if remember_me.count() > 0:
            expect(remember_me.first).to_be_visible()


@pytest.mark.e2e
class TestUserLogout:
    """E2E tests for user logout flow."""

    def test__logout__clears_session(self, auth_page: Page, live_server):
        """Test logout clears user session."""
        # User is already logged in via auth_page fixture

        # Find and click logout button/link
        logout = auth_page.locator("a[href*='logout'], button:has-text('Log Out'), button:has-text('Sign Out')")

        if logout.count() > 0:
            logout.first.click()

            # Should be logged out
            auth_page.wait_for_url("**/*")

            # Try to access protected page
            auth_page.goto(f"{live_server.url}/accounts/profile/")

            # Should redirect to login
            expect(auth_page).to_have_url("**/login/**")


@pytest.mark.e2e
class TestPasswordReset:
    """E2E tests for password reset flow."""

    def test__password_reset_page__displays_form(self, page: Page, live_server):
        """Test password reset page displays the form."""
        page.goto(f"{live_server.url}/accounts/password/reset/")

        email_input = page.locator("input[type='email'], input[name='email']")
        expect(email_input.first).to_be_visible()

    def test__password_reset__valid_email__shows_confirmation(self, page: Page, live_server, regular_user):
        """Test password reset with valid email shows confirmation."""
        page.goto(f"{live_server.url}/accounts/password/reset/")

        email_input = page.locator("input[type='email'], input[name='email']")
        email_input.first.fill("testuser@example.com")

        page.get_by_role("button", name="Reset Password").click()

        # Should show confirmation message
        page.wait_for_timeout(500)

        # Look for success message or confirmation page
        success = page.locator(".success, .alert-success, [role='alert']")

        # Or check URL changed to done page
        if success.count() == 0:
            expect(page).to_have_url("**/done/**")


@pytest.mark.e2e
class TestUserProfile:
    """E2E tests for user profile management."""

    def test__profile_page__displays_user_info(self, auth_page: Page, live_server):
        """Test profile page displays user information."""
        auth_page.goto(f"{live_server.url}/accounts/profile/")

        # Should display username
        expect(auth_page.get_by_text("testuser")).to_be_visible()

    def test__profile_page__edit_profile_link(self, auth_page: Page, live_server):
        """Test profile page has edit profile link/button."""
        auth_page.goto(f"{live_server.url}/accounts/profile/")

        edit_link = auth_page.locator("a[href*='edit'], button:has-text('Edit')")

        if edit_link.count() > 0:
            expect(edit_link.first).to_be_visible()

    def test__profile_edit__updates_info(self, auth_page: Page, live_server):
        """Test editing profile updates user information."""
        auth_page.goto(f"{live_server.url}/accounts/profile/edit/")

        # Find bio/about field if present
        bio_field = auth_page.locator("textarea[name='bio'], textarea[name='about']")

        if bio_field.count() > 0:
            bio_field.first.fill("Updated bio from E2E test")

            auth_page.get_by_role("button", name="Save").click()

            # Should redirect back to profile
            auth_page.wait_for_url("**/profile/**")


@pytest.mark.e2e
class TestProtectedRoutes:
    """E2E tests for protected route access."""

    def test__protected_route__unauthenticated__redirects_to_login(self, page: Page, live_server):
        """Test accessing protected route redirects to login."""
        page.goto(f"{live_server.url}/accounts/profile/")

        # Should redirect to login
        expect(page).to_have_url("**/login/**")

    def test__protected_route__authenticated__allows_access(self, auth_page: Page, live_server):
        """Test authenticated user can access protected routes."""
        auth_page.goto(f"{live_server.url}/accounts/profile/")

        # Should not redirect to login
        expect(auth_page).not_to_have_url("**/login/**")

    def test__admin_route__regular_user__denied(self, auth_page: Page, live_server):
        """Test regular user cannot access admin routes."""
        auth_page.goto(f"{live_server.url}/admin/")

        # Should show login or forbidden
        # Admin login page or 403

    def test__moderator_route__moderator__allows_access(self, mod_page: Page, live_server):
        """Test moderator can access moderation routes."""
        mod_page.goto(f"{live_server.url}/moderation/")

        # Should not redirect to login (moderator has access)
        expect(mod_page).not_to_have_url("**/login/**")
