"""Integration tests for authentication endpoints."""

import pytest
from httpx import AsyncClient


class TestAuthentication:
    """Test suite for authentication endpoints."""

    @pytest.mark.asyncio
    async def test_register_user(self, client: AsyncClient):
        """Test user registration."""
        user_data = {
            "email": "newuser@example.com",
            "password": "SecurePass123!",
            "name": "New User"
        }

        response = await client.post("/api/v1/auth/register", json=user_data)

        assert response.status_code == 201
        data = response.json()
        assert data["email"] == user_data["email"]
        assert data["name"] == user_data["name"]
        assert data["role"] == "engineer"
        assert "account_id" in data
        assert data["account_role"] == "owner"
        assert "id" in data
        assert "password" not in data  # Password should not be returned

    @pytest.mark.asyncio
    async def test_register_duplicate_email(
        self, client: AsyncClient, test_user: dict
    ):
        """Test that registering with duplicate email fails."""
        user_data = {
            "email": test_user["email"],  # Use existing email
            "password": "AnotherPass123!",
            "name": "Another User"
        }

        response = await client.post("/api/v1/auth/register", json=user_data)

        assert response.status_code == 400
        assert "already registered" in response.json()["detail"].lower()

    @pytest.mark.asyncio
    async def test_login_json(self, client: AsyncClient, test_user: dict):
        """Test JSON login endpoint."""
        login_data = {
            "email": test_user["email"],
            "password": test_user["password"]
        }

        response = await client.post("/api/v1/auth/login/json", json=login_data)

        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        assert "refresh_token" in data
        assert data["token_type"] == "bearer"

    @pytest.mark.asyncio
    async def test_login_invalid_credentials(
        self, client: AsyncClient, test_user: dict
    ):
        """Test login with wrong password."""
        login_data = {
            "email": test_user["email"],
            "password": "WrongPassword123!"
        }

        response = await client.post("/api/v1/auth/login/json", json=login_data)

        assert response.status_code == 401
        assert "incorrect" in response.json()["detail"].lower()

    @pytest.mark.asyncio
    async def test_get_current_user(
        self, client: AsyncClient, auth_headers: dict, test_user: dict
    ):
        """Test getting current authenticated user."""
        response = await client.get("/api/v1/auth/me", headers=auth_headers)

        assert response.status_code == 200
        data = response.json()
        assert data["email"] == test_user["email"]
        assert "password" not in data

    @pytest.mark.asyncio
    async def test_get_current_user_unauthorized(self, client: AsyncClient):
        """Test that unauthenticated request fails."""
        response = await client.get("/api/v1/auth/me")

        assert response.status_code == 401

    @pytest.mark.asyncio
    async def test_register_with_role_field_ignored(self, client: AsyncClient):
        """Test that sending a role field at registration is ignored — always engineer."""
        user_data = {
            "email": "hacker@example.com",
            "password": "HackerPass123!",
            "name": "Hacker",
            "role": "admin"
        }

        response = await client.post("/api/v1/auth/register", json=user_data)

        assert response.status_code == 201
        data = response.json()
        assert data["role"] == "engineer"
        assert data["account_role"] == "owner"

    @pytest.mark.asyncio
    async def test_register_default_role_is_engineer(self, client: AsyncClient):
        """Test that omitting role defaults to engineer."""
        user_data = {
            "email": "default@example.com",
            "password": "DefaultPass123!",
            "name": "Default User"
        }

        response = await client.post("/api/v1/auth/register", json=user_data)

        assert response.status_code == 201
        assert response.json()["role"] == "engineer"
        assert response.json()["account_role"] == "owner"

    @pytest.mark.asyncio
    async def test_register_rejects_no_uppercase(self, client: AsyncClient):
        """Test that password without uppercase is rejected."""
        user_data = {
            "email": "weak1@example.com",
            "password": "alllowercase123",
            "name": "Weak User"
        }
        response = await client.post("/api/v1/auth/register", json=user_data)
        assert response.status_code == 422

    @pytest.mark.asyncio
    async def test_register_rejects_no_lowercase(self, client: AsyncClient):
        """Test that password without lowercase is rejected."""
        user_data = {
            "email": "weak2@example.com",
            "password": "ALLUPPERCASE123",
            "name": "Weak User"
        }
        response = await client.post("/api/v1/auth/register", json=user_data)
        assert response.status_code == 422

    @pytest.mark.asyncio
    async def test_register_rejects_no_digit(self, client: AsyncClient):
        """Test that password without digit is rejected."""
        user_data = {
            "email": "weak3@example.com",
            "password": "NoDigitsHere!!",
            "name": "Weak User"
        }
        response = await client.post("/api/v1/auth/register", json=user_data)
        assert response.status_code == 422
