"""
Tests for authentication endpoints.
"""
import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.models import User
from app.core.security import hash_password, create_access_token


class TestAuthentication:
    """Test authentication endpoints."""
    
    @pytest.mark.asyncio
    async def test_login_success(self, client: AsyncClient, test_user: User):
        """Test successful login."""
        response = await client.post(
            "/auth/login",
            json={
                "username": "regular_test",
                "password": "testpassword123",
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        assert "refresh_token" in data
        assert data["user"]["username"] == "regular_test"
    
    @pytest.mark.asyncio
    async def test_login_invalid_password(self, client: AsyncClient, test_user: User):
        """Test login with invalid password."""
        response = await client.post(
            "/auth/login",
            json={
                "username": "regular_test",
                "password": "wrongpassword",
            },
        )
        assert response.status_code == 401
        assert response.json()["detail"] == "Invalid username or password"
    
    @pytest.mark.asyncio
    async def test_login_nonexistent_user(self, client: AsyncClient):
        """Test login with non-existent user."""
        response = await client.post(
            "/auth/login",
            json={
                "username": "nonexistent",
                "password": "password123",
            },
        )
        assert response.status_code == 401
        assert response.json()["detail"] == "Invalid username or password"
    
    @pytest.mark.asyncio
    async def test_register_success(self, client: AsyncClient):
        """Test successful user registration."""
        response = await client.post(
            "/auth/register",
            json={
                "username": "newuser",
                "password": "newpassword123",
                "email": "new@example.com",
                "country": "US",
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert data["username"] == "newuser"
        assert data["email"] == "new@example.com"
    
    @pytest.mark.asyncio
    async def test_register_duplicate_username(self, client: AsyncClient, test_user: User):
        """Test registration with duplicate username."""
        response = await client.post(
            "/auth/register",
            json={
                "username": "regular_test",  # Already exists
                "password": "newpassword123",
                "email": "new@example.com",
            },
        )
        assert response.status_code == 409
        assert response.json()["detail"] == "Username already exists"
    
    @pytest.mark.asyncio
    async def test_get_current_user(self, client: AsyncClient, regular_token: str):
        """Test getting current user."""
        response = await client.get(
            "/auth/me",
            params={"token": regular_token},
        )
        assert response.status_code == 200
        data = response.json()
        assert data["username"] == "regular_test"
    
    @pytest.mark.asyncio
    async def test_refresh_token(self, client: AsyncClient, test_user: User):
        """Test refreshing access token."""
        from app.core.security import create_refresh_token
        
        # First login to get refresh token
        login_response = await client.post(
            "/auth/login",
            json={
                "username": "regular_test",
                "password": "testpassword123",
            },
        )
        refresh_token = login_response.json()["refresh_token"]
        
        # Refresh token
        response = await client.post(
            "/auth/refresh",
            json={
                "refresh_token": refresh_token,
            },
        )
        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
