"""
Integration Tests for Full Authentication Flow.

These tests verify the complete authentication flow from
registration to login to logout.
"""
import pytest
from rest_framework import status


@pytest.mark.django_db
class TestAuthenticationFlow:
    """Integration tests for complete auth flow."""

    def test_full_registration_login_flow(self, api_client):
        """Test complete flow: register -> login -> access protected -> logout."""
        email = 'newuser@example.com'
        password = 'StrongPass123!'
        
        # Step 1: Register new user
        register_response = api_client.post('/api/v1/auth/register/', {
            'email': email,
            'password': password,
            'password_confirm': password,
            'first_name': 'New',
            'last_name': 'User',
        }, format='json')
        
        assert register_response.status_code == status.HTTP_201_CREATED
        assert 'email' in register_response.data
        
        # Step 2: Login with new credentials
        login_response = api_client.post('/api/v1/auth/login/', {
            'email': email,
            'password': password,
        }, format='json')
        
        assert login_response.status_code == status.HTTP_200_OK
        assert 'tokens' in login_response.data
        access_token = login_response.data['tokens']['access']
        refresh_token = login_response.data['tokens']['refresh']
        
        # Step 3: Access protected endpoint with token
        api_client.credentials(HTTP_AUTHORIZATION=f'Bearer {access_token}')
        profile_response = api_client.get('/api/v1/auth/profile/')
        
        assert profile_response.status_code == status.HTTP_200_OK
        profile_data = profile_response.data.get('data', profile_response.data)
        assert profile_data['email'] == email
        
        # Step 4: Logout
        logout_response = api_client.post('/api/v1/auth/logout/', {
            'refresh': refresh_token,
        }, format='json')
        
        assert logout_response.status_code == status.HTTP_200_OK

    def test_token_refresh_flow(self, api_client, create_user):
        """Test token refresh flow."""
        email = 'refreshtest@example.com'
        password = 'testpass123'
        create_user(email=email, password=password)
        
        # Login to get tokens
        login_response = api_client.post('/api/v1/auth/login/', {
            'email': email,
            'password': password,
        }, format='json')
        
        assert login_response.status_code == status.HTTP_200_OK
        refresh_token = login_response.data['tokens']['refresh']
        
        # Refresh token
        refresh_response = api_client.post('/api/v1/auth/refresh/', {
            'refresh': refresh_token,
        }, format='json')
        
        assert refresh_response.status_code == status.HTTP_200_OK
        assert 'access' in refresh_response.data

    def test_unauthorized_access_to_protected_endpoint(self, api_client):
        """Test that protected endpoints reject unauthorized access."""
        # Try to access profile without authentication
        response = api_client.get('/api/v1/auth/profile/')
        
        assert response.status_code == status.HTTP_401_UNAUTHORIZED

    def test_invalid_token_rejected(self, api_client):
        """Test that invalid tokens are rejected."""
        api_client.credentials(HTTP_AUTHORIZATION='Bearer invalid.token.here')
        response = api_client.get('/api/v1/auth/profile/')
        
        assert response.status_code == status.HTTP_401_UNAUTHORIZED


@pytest.mark.django_db
class TestUserProfileFlow:
    """Integration tests for user profile operations."""

    def test_view_and_update_profile(self, authenticated_client):
        """Test viewing and updating user profile."""
        client, user = authenticated_client
        
        # View profile
        response = client.get('/api/v1/auth/profile/')
        assert response.status_code == status.HTTP_200_OK
        profile_data = response.data.get('data', response.data)
        assert profile_data['email'] == user.email
        
        # Update profile
        update_response = client.patch('/api/v1/auth/profile/', {
            'first_name': 'Updated',
            'last_name': 'Name',
        }, format='json')
        
        assert update_response.status_code == status.HTTP_200_OK
        updated_data = update_response.data.get('data', update_response.data)
        assert updated_data['first_name'] == 'Updated'
        assert updated_data['last_name'] == 'Name'

    def test_cannot_change_email_via_profile_update(self, authenticated_client):
        """Test that email cannot be changed via profile update."""
        client, user = authenticated_client
        original_email = user.email
        
        # Try to update email
        response = client.patch('/api/v1/auth/profile/', {
            'email': 'newemail@example.com',
        }, format='json')
        
        # Response might succeed but email should not change
        user.refresh_from_db()
        assert user.email == original_email


@pytest.mark.django_db
class TestMultipleUserIsolation:
    """Test that users cannot access each other's data."""

    def test_users_have_separate_profiles(self, api_client, create_user):
        """Test that each user has their own profile."""
        # Create two users
        user1 = create_user(email='user1@example.com', password='pass123')
        user2 = create_user(email='user2@example.com', password='pass123')
        
        # Login as user1
        login1 = api_client.post('/api/v1/auth/login/', {
            'email': 'user1@example.com',
            'password': 'pass123',
        }, format='json')
        token1 = login1.data['tokens']['access']
        
        # Get profile as user1
        api_client.credentials(HTTP_AUTHORIZATION=f'Bearer {token1}')
        profile1 = api_client.get('/api/v1/auth/profile/')
        
        profile1_data = profile1.data.get('data', profile1.data)
        assert profile1_data['email'] == 'user1@example.com'
        
        # Login as user2
        api_client.credentials()  # Clear credentials
        login2 = api_client.post('/api/v1/auth/login/', {
            'email': 'user2@example.com',
            'password': 'pass123',
        }, format='json')
        token2 = login2.data['tokens']['access']
        
        # Get profile as user2
        api_client.credentials(HTTP_AUTHORIZATION=f'Bearer {token2}')
        profile2 = api_client.get('/api/v1/auth/profile/')
        
        profile2_data = profile2.data.get('data', profile2.data)
        assert profile2_data['email'] == 'user2@example.com'
