"""Tests for authentication API endpoints."""

import pytest
from uuid import UUID

from vikdata.client import VikdataClient
from vikdata.exceptions import AuthenticationError, ValidationError
from vikdata.models.auth import (
    AccessTokenResponse,
    LogoutResponse,
    TokenResponse,
    UserResponse,
)


@pytest.fixture
def mock_token_response():
    """Mock token response data."""
    return {
        "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
        "token_type": "bearer",
        "expires_in": 3600,
    }


@pytest.fixture
def mock_user_response():
    """Mock user response data."""
    return {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "tenant_id": "550e8400-e29b-41d4-a716-446655440001",
        "email": "test@example.com",
        "name": "Test User",
        "permissions": ["users:read:*", "roles:read:*"],
        "roles": ["admin"],
    }


@pytest.mark.asyncio
async def test_login_success(respx_mock, mock_token_response):
    """Test successful login."""
    respx_mock.post("http://localhost:8000/api/v1/auth/login").mock(
        return_value={"json": mock_token_response, "status_code": 200}
    )

    async with VikdataClient(base_url="http://localhost:8000") as client:
        response = await client.auth.login("test@example.com", "password123")

        assert isinstance(response, TokenResponse)
        assert response.access_token == mock_token_response["access_token"]
        assert response.refresh_token == mock_token_response["refresh_token"]
        assert response.token_type == "bearer"
        assert response.expires_in == 3600
        # Verify token was set on client
        assert client.access_token == mock_token_response["access_token"]


@pytest.mark.asyncio
async def test_login_invalid_credentials(respx_mock):
    """Test login with invalid credentials."""
    respx_mock.post("http://localhost:8000/api/v1/auth/login").mock(
        return_value={
            "json": {"message": "Invalid credentials"},
            "status_code": 401,
        }
    )

    async with VikdataClient(base_url="http://localhost:8000") as client:
        with pytest.raises(AuthenticationError):
            await client.auth.login("test@example.com", "wrong_password")


@pytest.mark.asyncio
async def test_refresh_token(respx_mock):
    """Test token refresh."""
    mock_response = {
        "access_token": "new_access_token_here",
        "token_type": "bearer",
        "expires_in": 3600,
    }

    respx_mock.post("http://localhost:8000/api/v1/auth/refresh").mock(
        return_value={"json": mock_response, "status_code": 200}
    )

    async with VikdataClient(base_url="http://localhost:8000") as client:
        response = await client.auth.refresh("old_refresh_token")

        assert isinstance(response, AccessTokenResponse)
        assert response.access_token == "new_access_token_here"
        assert client.access_token == "new_access_token_here"


@pytest.mark.asyncio
async def test_logout(respx_mock):
    """Test logout."""
    respx_mock.post("http://localhost:8000/api/v1/auth/logout").mock(
        return_value={
            "json": {"message": "Successfully logged out"},
            "status_code": 200,
        }
    )

    async with VikdataClient(
        base_url="http://localhost:8000", access_token="test_token"
    ) as client:
        response = await client.auth.logout()

        assert isinstance(response, LogoutResponse)
        assert response.message == "Successfully logged out"
        # Verify token was cleared
        assert client.access_token is None


@pytest.mark.asyncio
async def test_get_current_user(respx_mock, mock_user_response):
    """Test getting current user info."""
    respx_mock.get("http://localhost:8000/api/v1/auth/me").mock(
        return_value={"json": mock_user_response, "status_code": 200}
    )

    async with VikdataClient(
        base_url="http://localhost:8000", access_token="test_token"
    ) as client:
        response = await client.auth.me()

        assert isinstance(response, UserResponse)
        assert response.email == "test@example.com"
        assert response.name == "Test User"
        assert "users:read:*" in response.permissions
        assert "admin" in response.roles


@pytest.mark.asyncio
async def test_get_current_user_unauthorized(respx_mock):
    """Test getting current user without authentication."""
    respx_mock.get("http://localhost:8000/api/v1/auth/me").mock(
        return_value={
            "json": {"message": "Not authenticated"},
            "status_code": 401,
        }
    )

    async with VikdataClient(base_url="http://localhost:8000") as client:
        with pytest.raises(AuthenticationError):
            await client.auth.me()
