# -*- coding: utf-8 -*-
"""
Accounts Tests

This module contains comprehensive tests for the accounts app,
covering models, views, forms, serializers, services, and tasks.

Test Categories:
    - Model Tests: User model functionality
    - Form Tests: Form validation and processing
    - View Tests: Web views and API endpoints
    - Serializer Tests: API serialization
    - Service Tests: Business logic
    - Task Tests: Celery tasks
    - Integration Tests: End-to-end workflows
    - Permission Tests: Access control
    - Security Tests: Authentication and authorization

Features:
    - Comprehensive test coverage
    - Mock external dependencies
    - Test data factories
    - Performance testing
    - Security testing
    - API testing
    - Form validation testing
    - Database testing

Usage:
    Run all tests:
        python manage.py test apps.accounts
    
    Run specific test class:
        python manage.py test apps.accounts.tests.UserModelTests
    
    Run with coverage:
        coverage run --source='.' manage.py test apps.accounts
        coverage report

Requirements:
    - Django test framework
    - Factory Boy for test data
    - Mock for external dependencies
    - Coverage for test coverage
"""

import json
import tempfile
from datetime import datetime, timedelta
from unittest.mock import patch, Mock, MagicMock
from io import BytesIO

from django.test import TestCase, TransactionTestCase, Client
from django.test.utils import override_settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.utils import timezone
from django.db import IntegrityError

from rest_framework.test import APITestCase, APIClient
from rest_framework import status
from rest_framework.authtoken.models import Token

from apps.activities.models import Activity
from .models import User
from .forms import UserCreationForm, UserUpdateForm, ProfileForm, BulkUserActionForm
from .serializers import (
    UserSerializer, UserDetailSerializer, UserCreateSerializer,
    UserUpdateSerializer, UserListSerializer, PasswordChangeSerializer,
    BulkUserActionSerializer
)
from .services import UserService, AuthenticationService, ProfileService, ExportService
from .tasks import (
    send_welcome_email_task, send_password_reset_email_task,
    cleanup_inactive_users_task, generate_user_report_task,
    bulk_user_operation_task
)

User = get_user_model()


# ============================================================================
# Test Utilities and Factories
# ============================================================================

class UserFactory:
    """
    Factory for creating test users.
    """
    
    @staticmethod
    def create_user(**kwargs):
        defaults = {
            'email': 'test@example.com',
            'first_name': 'Test',
            'last_name': 'User',
            'is_active': True,
        }
        defaults.update(kwargs)
        
        if 'password' in defaults:
            password = defaults.pop('password')
            user = User.objects.create_user(**defaults)
            user.set_password(password)
            user.save()
            return user
        
        return User.objects.create_user(**defaults)
    
    @staticmethod
    def create_superuser(**kwargs):
        defaults = {
            'email': 'admin@example.com',
            'first_name': 'Admin',
            'last_name': 'User',
        }
        defaults.update(kwargs)
        return User.objects.create_superuser(**defaults)
    
    @staticmethod
    def create_staff_user(**kwargs):
        defaults = {
            'email': 'staff@example.com',
            'first_name': 'Staff',
            'last_name': 'User',
            'is_staff': True,
        }
        defaults.update(kwargs)
        return UserFactory.create_user(**defaults)


class BaseTestCase(TestCase):
    """
    Base test case with common setup.
    """
    
    def setUp(self):
        self.client = Client()
        self.user = UserFactory.create_user(
            email='testuser@example.com',
            password='testpass123'
        )
        self.admin_user = UserFactory.create_superuser(
            email='admin@example.com',
            password='adminpass123'
        )
        self.staff_user = UserFactory.create_staff_user(
            email='staff@example.com',
            password='staffpass123'
        )


# ============================================================================
# Model Tests
# ============================================================================

class UserModelTests(TestCase):
    """
    Test cases for the User model.
    """
    
    def test_create_user(self):
        """Test creating a regular user."""
        user = User.objects.create_user(
            email='test@example.com',
            first_name='Test',
            last_name='User'
        )
        
        self.assertEqual(user.email, 'test@example.com')
        self.assertEqual(user.first_name, 'Test')
        self.assertEqual(user.last_name, 'User')
        self.assertTrue(user.is_active)
        self.assertFalse(user.is_staff)
        self.assertFalse(user.is_superuser)
        self.assertIsNotNone(user.date_joined)
    
    def test_create_superuser(self):
        """Test creating a superuser."""
        user = User.objects.create_superuser(
            email='admin@example.com',
            first_name='Admin',
            last_name='User'
        )
        
        self.assertEqual(user.email, 'admin@example.com')
        self.assertTrue(user.is_active)
        self.assertTrue(user.is_staff)
        self.assertTrue(user.is_superuser)
    
    def test_email_normalization(self):
        """Test email normalization."""
        user = User.objects.create_user(
            email='Test@EXAMPLE.COM',
            first_name='Test',
            last_name='User'
        )
        
        self.assertEqual(user.email, 'test@example.com')
    
    def test_unique_email(self):
        """Test email uniqueness constraint."""
        User.objects.create_user(
            email='test@example.com',
            first_name='Test',
            last_name='User'
        )
        
        with self.assertRaises(IntegrityError):
            User.objects.create_user(
                email='test@example.com',
                first_name='Another',
                last_name='User'
            )
    
    def test_get_full_name(self):
        """Test get_full_name method."""
        user = UserFactory.create_user(
            first_name='John',
            last_name='Doe'
        )
        
        self.assertEqual(user.get_full_name(), 'John Doe')
    
    def test_get_short_name(self):
        """Test get_short_name method."""
        user = UserFactory.create_user(first_name='John')
        
        self.assertEqual(user.get_short_name(), 'John')
    
    def test_str_representation(self):
        """Test string representation."""
        user = UserFactory.create_user(email='test@example.com')
        
        self.assertEqual(str(user), 'test@example.com')
    
    def test_user_permissions(self):
        """Test user permissions."""
        user = UserFactory.create_user()
        
        # Test default permissions
        self.assertFalse(user.has_perm('accounts.add_user'))
        self.assertFalse(user.has_perm('accounts.change_user'))
        self.assertFalse(user.has_perm('accounts.delete_user'))
        
        # Test superuser permissions
        superuser = UserFactory.create_superuser()
        self.assertTrue(superuser.has_perm('accounts.add_user'))
        self.assertTrue(superuser.has_perm('accounts.change_user'))
        self.assertTrue(superuser.has_perm('accounts.delete_user'))
    
    def test_user_groups(self):
        """Test user groups functionality."""
        user = UserFactory.create_user()
        group = Group.objects.create(name='Test Group')
        
        user.groups.add(group)
        
        self.assertIn(group, user.groups.all())
        self.assertTrue(user.groups.filter(name='Test Group').exists())
    
    def test_user_avatar_upload(self):
        """Test avatar upload functionality."""
        user = UserFactory.create_user()
        
        # Create a simple test image
        image_content = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\tpHYs\x00\x00\x0b\x13\x00\x00\x0b\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\nIDATx\x9cc```\x00\x00\x00\x02\x00\x01H\xaf\xa4q\x00\x00\x00\x00IEND\xaeB`\x82'
        avatar_file = SimpleUploadedFile(
            'test_avatar.png',
            image_content,
            content_type='image/png'
        )
        
        user.avatar = avatar_file
        user.save()
        
        self.assertTrue(user.avatar)
        self.assertIn('test_avatar', user.avatar.name)


# ============================================================================
# Form Tests
# ============================================================================

class UserFormTests(TestCase):
    """
    Test cases for user forms.
    """
    
    def test_user_creation_form_valid(self):
        """Test valid user creation form."""
        form_data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password1': 'complexpass123',
            'password2': 'complexpass123',
        }
        
        form = UserCreationForm(data=form_data)
        self.assertTrue(form.is_valid())
        
        user = form.save()
        self.assertEqual(user.email, 'newuser@example.com')
        self.assertEqual(user.first_name, 'New')
        self.assertEqual(user.last_name, 'User')
    
    def test_user_creation_form_password_mismatch(self):
        """Test user creation form with password mismatch."""
        form_data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password1': 'complexpass123',
            'password2': 'differentpass123',
        }
        
        form = UserCreationForm(data=form_data)
        self.assertFalse(form.is_valid())
        self.assertIn('password2', form.errors)
    
    def test_user_creation_form_duplicate_email(self):
        """Test user creation form with duplicate email."""
        UserFactory.create_user(email='existing@example.com')
        
        form_data = {
            'email': 'existing@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password1': 'complexpass123',
            'password2': 'complexpass123',
        }
        
        form = UserCreationForm(data=form_data)
        self.assertFalse(form.is_valid())
        self.assertIn('email', form.errors)
    
    def test_user_update_form_valid(self):
        """Test valid user update form."""
        user = UserFactory.create_user()
        
        form_data = {
            'first_name': 'Updated',
            'last_name': 'Name',
            'email': 'updated@example.com',
            'phone': '+1234567890',
            'bio': 'Updated bio',
        }
        
        form = UserUpdateForm(data=form_data, instance=user)
        self.assertTrue(form.is_valid())
        
        updated_user = form.save()
        self.assertEqual(updated_user.first_name, 'Updated')
        self.assertEqual(updated_user.last_name, 'Name')
        self.assertEqual(updated_user.email, 'updated@example.com')
    
    def test_profile_form_valid(self):
        """Test valid profile form."""
        user = UserFactory.create_user()
        
        form_data = {
            'first_name': 'Updated',
            'last_name': 'Profile',
            'phone': '+1234567890',
            'bio': 'My bio',
            'location': 'New York',
            'website': 'https://example.com',
            'birth_date': '1990-01-01',
        }
        
        form = ProfileForm(data=form_data, instance=user)
        self.assertTrue(form.is_valid())
    
    def test_bulk_user_action_form_valid(self):
        """Test valid bulk user action form."""
        users = [UserFactory.create_user() for _ in range(3)]
        user_ids = [str(user.id) for user in users]
        
        form_data = {
            'action': 'activate',
            'user_ids': ','.join(user_ids),
        }
        
        form = BulkUserActionForm(data=form_data)
        self.assertTrue(form.is_valid())
        
        cleaned_data = form.cleaned_data
        self.assertEqual(cleaned_data['action'], 'activate')
        self.assertEqual(len(cleaned_data['user_ids']), 3)


# ============================================================================
# View Tests
# ============================================================================

class UserViewTests(BaseTestCase):
    """
    Test cases for user views.
    """
    
    def test_user_list_view_authenticated(self):
        """Test user list view with authenticated user."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        response = self.client.get(reverse('accounts:user_list'))
        
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'testuser@example.com')
        self.assertContains(response, 'admin@example.com')
    
    def test_user_list_view_unauthenticated(self):
        """Test user list view with unauthenticated user."""
        response = self.client.get(reverse('accounts:user_list'))
        
        self.assertEqual(response.status_code, 302)  # Redirect to login
    
    def test_user_detail_view(self):
        """Test user detail view."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        response = self.client.get(
            reverse('accounts:user_detail', kwargs={'pk': self.user.pk})
        )
        
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, self.user.email)
        self.assertContains(response, self.user.get_full_name())
    
    def test_user_create_view_get(self):
        """Test user create view GET request."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        response = self.client.get(reverse('accounts:user_create'))
        
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'Create User')
    
    def test_user_create_view_post_valid(self):
        """Test user create view POST request with valid data."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        form_data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password1': 'complexpass123',
            'password2': 'complexpass123',
        }
        
        response = self.client.post(reverse('accounts:user_create'), data=form_data)
        
        self.assertEqual(response.status_code, 302)  # Redirect after success
        self.assertTrue(User.objects.filter(email='newuser@example.com').exists())
    
    def test_user_update_view(self):
        """Test user update view."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        form_data = {
            'first_name': 'Updated',
            'last_name': 'Name',
            'email': self.user.email,
        }
        
        response = self.client.post(
            reverse('accounts:user_update', kwargs={'pk': self.user.pk}),
            data=form_data
        )
        
        self.assertEqual(response.status_code, 302)
        
        self.user.refresh_from_db()
        self.assertEqual(self.user.first_name, 'Updated')
        self.assertEqual(self.user.last_name, 'Name')
    
    def test_user_delete_view(self):
        """Test user delete view."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        user_to_delete = UserFactory.create_user(email='delete@example.com')
        
        response = self.client.post(
            reverse('accounts:user_delete', kwargs={'pk': user_to_delete.pk})
        )
        
        self.assertEqual(response.status_code, 302)
        self.assertFalse(User.objects.filter(id=user_to_delete.id).exists())
    
    def test_profile_view(self):
        """Test profile view."""
        self.client.login(email='testuser@example.com', password='testpass123')
        
        response = self.client.get(reverse('accounts:profile'))
        
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, self.user.email)
    
    def test_profile_update_view(self):
        """Test profile update view."""
        self.client.login(email='testuser@example.com', password='testpass123')
        
        form_data = {
            'first_name': 'Updated',
            'last_name': 'Profile',
            'phone': '+1234567890',
            'bio': 'Updated bio',
        }
        
        response = self.client.post(
            reverse('accounts:profile_update'),
            data=form_data
        )
        
        self.assertEqual(response.status_code, 302)
        
        self.user.refresh_from_db()
        self.assertEqual(self.user.first_name, 'Updated')
        self.assertEqual(self.user.last_name, 'Profile')
    
    def test_password_change_view(self):
        """Test password change view."""
        self.client.login(email='testuser@example.com', password='testpass123')
        
        form_data = {
            'old_password': 'testpass123',
            'new_password1': 'newcomplexpass123',
            'new_password2': 'newcomplexpass123',
        }
        
        response = self.client.post(
            reverse('accounts:password_change'),
            data=form_data
        )
        
        self.assertEqual(response.status_code, 302)
        
        # Test new password works
        self.client.logout()
        login_success = self.client.login(
            email='testuser@example.com',
            password='newcomplexpass123'
        )
        self.assertTrue(login_success)


class AjaxViewTests(BaseTestCase):
    """
    Test cases for AJAX views.
    """
    
    def test_user_search_ajax(self):
        """Test user search AJAX endpoint."""
        self.client.login(email='testuser@example.com', password='testpass123')
        
        response = self.client.get(
            reverse('accounts:ajax_search'),
            {'q': 'test'}
        )
        
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.content)
        self.assertIn('users', data)
        self.assertTrue(len(data['users']) > 0)
    
    def test_toggle_user_status_ajax(self):
        """Test toggle user status AJAX endpoint."""
        self.client.login(email='admin@example.com', password='adminpass123')
        
        original_status = self.user.is_active
        
        response = self.client.post(
            reverse('accounts:ajax_toggle_status', kwargs={'pk': self.user.pk})
        )
        
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.content)
        self.assertTrue(data['success'])
        
        self.user.refresh_from_db()
        self.assertNotEqual(self.user.is_active, original_status)
    
    def test_user_info_ajax(self):
        """Test user info AJAX endpoint."""
        self.client.login(email='testuser@example.com', password='testpass123')
        
        response = self.client.get(
            reverse('accounts:ajax_user_info', kwargs={'pk': self.user.pk})
        )
        
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.content)
        self.assertTrue(data['success'])
        self.assertEqual(data['user']['email'], self.user.email)
    
    def test_check_email_ajax(self):
        """Test check email availability AJAX endpoint."""
        response = self.client.get(
            reverse('accounts:ajax_check_email'),
            {'email': 'available@example.com'}
        )
        
        self.assertEqual(response.status_code, 200)
        data = json.loads(response.content)
        self.assertTrue(data['available'])
        
        # Test with existing email
        response = self.client.get(
            reverse('accounts:ajax_check_email'),
            {'email': self.user.email}
        )
        
        data = json.loads(response.content)
        self.assertFalse(data['available'])


# ============================================================================
# API Tests
# ============================================================================

class UserAPITests(APITestCase):
    """
    Test cases for User API endpoints.
    """
    
    def setUp(self):
        self.client = APIClient()
        self.user = UserFactory.create_user(
            email='testuser@example.com',
            password='testpass123'
        )
        self.admin_user = UserFactory.create_superuser(
            email='admin@example.com',
            password='adminpass123'
        )
    
    def test_user_list_api_authenticated(self):
        """Test user list API with authenticated user."""
        self.client.force_authenticate(user=self.user)
        
        response = self.client.get('/accounts/api/users/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('results', response.data)
    
    def test_user_list_api_unauthenticated(self):
        """Test user list API with unauthenticated user."""
        response = self.client.get('/accounts/api/users/')
        
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
    
    def test_user_create_api(self):
        """Test user creation via API."""
        data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password': 'complexpass123',
            'password_confirm': 'complexpass123'
        }
        
        response = self.client.post('/accounts/api/users/', data)
        
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertTrue(User.objects.filter(email='newuser@example.com').exists())
    
    def test_user_detail_api(self):
        """Test user detail API."""
        self.client.force_authenticate(user=self.user)
        
        response = self.client.get(f'/accounts/api/users/{self.user.id}/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['email'], self.user.email)
    
    def test_user_update_api(self):
        """Test user update via API."""
        self.client.force_authenticate(user=self.admin_user)
        
        data = {
            'first_name': 'Updated',
            'last_name': 'Name'
        }
        
        response = self.client.patch(f'/accounts/api/users/{self.user.id}/', data)
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        
        self.user.refresh_from_db()
        self.assertEqual(self.user.first_name, 'Updated')
        self.assertEqual(self.user.last_name, 'Name')
    
    def test_user_delete_api(self):
        """Test user deletion via API."""
        self.client.force_authenticate(user=self.admin_user)
        
        user_to_delete = UserFactory.create_user(email='delete@example.com')
        
        response = self.client.delete(f'/accounts/api/users/{user_to_delete.id}/')
        
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
        self.assertFalse(User.objects.filter(id=user_to_delete.id).exists())
    
    def test_login_api(self):
        """Test login API endpoint."""
        data = {
            'email': 'testuser@example.com',
            'password': 'testpass123'
        }
        
        response = self.client.post('/accounts/api/auth/login/', data)
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('user', response.data)
        self.assertEqual(response.data['user']['email'], self.user.email)
    
    def test_login_api_invalid_credentials(self):
        """Test login API with invalid credentials."""
        data = {
            'email': 'testuser@example.com',
            'password': 'wrongpassword'
        }
        
        response = self.client.post('/accounts/api/auth/login/', data)
        
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
    
    def test_logout_api(self):
        """Test logout API endpoint."""
        self.client.force_authenticate(user=self.user)
        
        response = self.client.post('/accounts/api/auth/logout/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
    
    def test_register_api(self):
        """Test registration API endpoint."""
        data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password': 'complexpass123',
            'password_confirm': 'complexpass123'
        }
        
        response = self.client.post('/accounts/api/auth/register/', data)
        
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertTrue(User.objects.filter(email='newuser@example.com').exists())
    
    def test_password_change_api(self):
        """Test password change API endpoint."""
        self.client.force_authenticate(user=self.user)
        
        data = {
            'old_password': 'testpass123',
            'new_password': 'newcomplexpass123',
            'new_password_confirm': 'newcomplexpass123'
        }
        
        response = self.client.post('/accounts/api/auth/password-change/', data)
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
    
    def test_profile_api(self):
        """Test profile API endpoint."""
        self.client.force_authenticate(user=self.user)
        
        response = self.client.get('/accounts/api/profile/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['email'], self.user.email)
    
    def test_user_statistics_api(self):
        """Test user statistics API endpoint."""
        self.client.force_authenticate(user=self.admin_user)
        
        response = self.client.get('/accounts/api/statistics/')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('total_users', response.data)
    
    def test_bulk_user_action_api(self):
        """Test bulk user action API endpoint."""
        self.client.force_authenticate(user=self.admin_user)
        
        users = [UserFactory.create_user() for _ in range(3)]
        user_ids = [user.id for user in users]
        
        data = {
            'action': 'activate',
            'user_ids': user_ids
        }
        
        response = self.client.post('/accounts/api/bulk/actions/', data)
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('task_id', response.data)
    
    def test_user_search_api(self):
        """Test user search API endpoint."""
        self.client.force_authenticate(user=self.user)
        
        response = self.client.get('/accounts/api/search/?search=test')
        
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertIn('results', response.data)


# ============================================================================
# Serializer Tests
# ============================================================================

class UserSerializerTests(TestCase):
    """
    Test cases for user serializers.
    """
    
    def setUp(self):
        self.user = UserFactory.create_user()
    
    def test_user_serializer(self):
        """Test UserSerializer."""
        serializer = UserSerializer(self.user)
        
        self.assertEqual(serializer.data['email'], self.user.email)
        self.assertEqual(serializer.data['first_name'], self.user.first_name)
        self.assertEqual(serializer.data['last_name'], self.user.last_name)
    
    def test_user_detail_serializer(self):
        """Test UserDetailSerializer."""
        serializer = UserDetailSerializer(self.user)
        
        self.assertEqual(serializer.data['email'], self.user.email)
        self.assertIn('date_joined', serializer.data)
        self.assertIn('last_login', serializer.data)
    
    def test_user_create_serializer_valid(self):
        """Test UserCreateSerializer with valid data."""
        data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password': 'complexpass123',
            'password_confirm': 'complexpass123'
        }
        
        serializer = UserCreateSerializer(data=data)
        self.assertTrue(serializer.is_valid())
        
        user = serializer.save()
        self.assertEqual(user.email, 'newuser@example.com')
    
    def test_user_create_serializer_password_mismatch(self):
        """Test UserCreateSerializer with password mismatch."""
        data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password': 'complexpass123',
            'password_confirm': 'differentpass123'
        }
        
        serializer = UserCreateSerializer(data=data)
        self.assertFalse(serializer.is_valid())
        self.assertIn('password_confirm', serializer.errors)
    
    def test_user_update_serializer(self):
        """Test UserUpdateSerializer."""
        data = {
            'first_name': 'Updated',
            'last_name': 'Name'
        }
        
        serializer = UserUpdateSerializer(self.user, data=data, partial=True)
        self.assertTrue(serializer.is_valid())
        
        updated_user = serializer.save()
        self.assertEqual(updated_user.first_name, 'Updated')
        self.assertEqual(updated_user.last_name, 'Name')
    
    def test_password_change_serializer_valid(self):
        """Test PasswordChangeSerializer with valid data."""
        data = {
            'old_password': 'testpass123',
            'new_password': 'newcomplexpass123',
            'new_password_confirm': 'newcomplexpass123'
        }
        
        # Mock request with user
        request = Mock()
        request.user = self.user
        
        serializer = PasswordChangeSerializer(
            data=data,
            context={'request': request}
        )
        self.assertTrue(serializer.is_valid())
    
    def test_bulk_user_action_serializer(self):
        """Test BulkUserActionSerializer."""
        users = [UserFactory.create_user() for _ in range(3)]
        user_ids = [user.id for user in users]
        
        data = {
            'action': 'activate',
            'user_ids': user_ids
        }
        
        serializer = BulkUserActionSerializer(data=data)
        self.assertTrue(serializer.is_valid())
        
        self.assertEqual(serializer.validated_data['action'], 'activate')
        self.assertEqual(len(serializer.validated_data['user_ids']), 3)


# ============================================================================
# Service Tests
# ============================================================================

class UserServiceTests(TestCase):
    """
    Test cases for UserService.
    """
    
    def setUp(self):
        self.user = UserFactory.create_user()
    
    def test_get_user_statistics(self):
        """Test get_user_statistics method."""
        stats = UserService.get_user_statistics(self.user)
        
        self.assertIn('total_activities', stats)
        self.assertIn('last_login', stats)
        self.assertIn('account_age_days', stats)
    
    def test_get_comprehensive_statistics(self):
        """Test get_comprehensive_statistics method."""
        stats = UserService.get_comprehensive_statistics()
        
        self.assertIn('total_users', stats)
        self.assertIn('active_users', stats)
        self.assertIn('inactive_users', stats)
        self.assertIn('new_users_today', stats)
    
    @patch('apps.accounts.tasks.send_welcome_email_task.delay')
    def test_create_user_with_welcome_email(self, mock_task):
        """Test creating user with welcome email."""
        user_data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password': 'complexpass123'
        }
        
        user = UserService.create_user_with_welcome_email(user_data)
        
        self.assertEqual(user.email, 'newuser@example.com')
        mock_task.assert_called_once_with(user.id)
    
    def test_activate_users(self):
        """Test activate_users method."""
        users = [UserFactory.create_user(is_active=False) for _ in range(3)]
        user_ids = [user.id for user in users]
        
        result = UserService.activate_users(user_ids)
        
        self.assertEqual(result['activated'], 3)
        
        for user in users:
            user.refresh_from_db()
            self.assertTrue(user.is_active)
    
    def test_deactivate_users(self):
        """Test deactivate_users method."""
        users = [UserFactory.create_user(is_active=True) for _ in range(3)]
        user_ids = [user.id for user in users]
        
        result = UserService.deactivate_users(user_ids)
        
        self.assertEqual(result['deactivated'], 3)
        
        for user in users:
            user.refresh_from_db()
            self.assertFalse(user.is_active)


class AuthenticationServiceTests(TestCase):
    """
    Test cases for AuthenticationService.
    """
    
    def setUp(self):
        self.user = UserFactory.create_user(
            email='test@example.com',
            password='testpass123'
        )
    
    def test_authenticate_user_valid(self):
        """Test authenticate_user with valid credentials."""
        user = AuthenticationService.authenticate_user(
            'test@example.com',
            'testpass123'
        )
        
        self.assertEqual(user, self.user)
    
    def test_authenticate_user_invalid_email(self):
        """Test authenticate_user with invalid email."""
        user = AuthenticationService.authenticate_user(
            'invalid@example.com',
            'testpass123'
        )
        
        self.assertIsNone(user)
    
    def test_authenticate_user_invalid_password(self):
        """Test authenticate_user with invalid password."""
        user = AuthenticationService.authenticate_user(
            'test@example.com',
            'wrongpassword'
        )
        
        self.assertIsNone(user)
    
    def test_authenticate_user_inactive(self):
        """Test authenticate_user with inactive user."""
        self.user.is_active = False
        self.user.save()
        
        user = AuthenticationService.authenticate_user(
            'test@example.com',
            'testpass123'
        )
        
        self.assertIsNone(user)


class ProfileServiceTests(TestCase):
    """
    Test cases for ProfileService.
    """
    
    def setUp(self):
        self.user = UserFactory.create_user()
    
    def test_update_profile(self):
        """Test update_profile method."""
        profile_data = {
            'first_name': 'Updated',
            'last_name': 'Name',
            'phone': '+1234567890',
            'bio': 'Updated bio'
        }
        
        updated_user = ProfileService.update_profile(self.user, profile_data)
        
        self.assertEqual(updated_user.first_name, 'Updated')
        self.assertEqual(updated_user.last_name, 'Name')
        self.assertEqual(updated_user.phone, '+1234567890')
        self.assertEqual(updated_user.bio, 'Updated bio')
    
    @patch('PIL.Image.open')
    def test_update_avatar(self, mock_image):
        """Test update_avatar method."""
        # Mock PIL Image
        mock_img = Mock()
        mock_img.size = (100, 100)
        mock_img.format = 'JPEG'
        mock_image.return_value = mock_img
        
        avatar_file = SimpleUploadedFile(
            'test_avatar.jpg',
            b'fake_image_content',
            content_type='image/jpeg'
        )
        
        ProfileService.update_avatar(self.user, avatar_file)
        
        self.user.refresh_from_db()
        self.assertTrue(self.user.avatar)


class ExportServiceTests(TestCase):
    """
    Test cases for ExportService.
    """
    
    def setUp(self):
        self.users = [UserFactory.create_user() for _ in range(5)]
    
    def test_export_users_csv(self):
        """Test export_users_csv method."""
        queryset = User.objects.all()
        
        response = ExportService.export_users_csv(queryset)
        
        self.assertEqual(response['Content-Type'], 'text/csv')
        self.assertIn('attachment', response['Content-Disposition'])
    
    def test_export_users_json(self):
        """Test export_users_json method."""
        queryset = User.objects.all()
        
        response = ExportService.export_users_json(queryset)
        
        self.assertEqual(response['Content-Type'], 'application/json')
        self.assertIn('attachment', response['Content-Disposition'])
    
    def test_import_users_from_csv(self):
        """Test import_users_from_csv method."""
        csv_content = (
            'email,first_name,last_name\n'
            'import1@example.com,Import,User1\n'
            'import2@example.com,Import,User2\n'
        )
        
        csv_file = SimpleUploadedFile(
            'users.csv',
            csv_content.encode('utf-8'),
            content_type='text/csv'
        )
        
        result = ExportService.import_users_from_file(csv_file)
        
        self.assertEqual(result['created'], 2)
        self.assertEqual(result['updated'], 0)
        self.assertTrue(User.objects.filter(email='import1@example.com').exists())
        self.assertTrue(User.objects.filter(email='import2@example.com').exists())


# ============================================================================
# Task Tests
# ============================================================================

class TaskTests(TestCase):
    """
    Test cases for Celery tasks.
    """
    
    def setUp(self):
        self.user = UserFactory.create_user()
    
    @patch('apps.core.utils.send_email_async')
    def test_send_welcome_email_task(self, mock_send_email):
        """Test send_welcome_email_task."""
        send_welcome_email_task(self.user.id)
        
        mock_send_email.assert_called_once()
        args, kwargs = mock_send_email.call_args
        self.assertEqual(kwargs['to_email'], self.user.email)
        self.assertIn('Welcome', kwargs['subject'])
    
    @patch('apps.core.utils.send_email_async')
    def test_send_password_reset_email_task(self, mock_send_email):
        """Test send_password_reset_email_task."""
        send_password_reset_email_task(self.user.id)
        
        mock_send_email.assert_called_once()
        args, kwargs = mock_send_email.call_args
        self.assertEqual(kwargs['to_email'], self.user.email)
        self.assertIn('Password Reset', kwargs['subject'])
    
    def test_cleanup_inactive_users_task(self):
        """Test cleanup_inactive_users_task."""
        # Create inactive users older than 30 days
        old_date = timezone.now() - timedelta(days=35)
        inactive_users = []
        
        for i in range(3):
            user = UserFactory.create_user(
                email=f'inactive{i}@example.com',
                is_active=False
            )
            user.date_joined = old_date
            user.save()
            inactive_users.append(user)
        
        # Create recent inactive user (should not be deleted)
        recent_inactive = UserFactory.create_user(
            email='recent@example.com',
            is_active=False
        )
        
        result = cleanup_inactive_users_task()
        
        self.assertEqual(result['deleted'], 3)
        
        # Check that old inactive users are deleted
        for user in inactive_users:
            self.assertFalse(User.objects.filter(id=user.id).exists())
        
        # Check that recent inactive user still exists
        self.assertTrue(User.objects.filter(id=recent_inactive.id).exists())
    
    @patch('apps.accounts.services.ExportService.generate_user_report')
    def test_generate_user_report_task(self, mock_generate_report):
        """Test generate_user_report_task."""
        mock_generate_report.return_value = {'total_users': 5}
        
        result = generate_user_report_task('csv')
        
        mock_generate_report.assert_called_once_with('csv')
        self.assertEqual(result['total_users'], 5)
    
    @patch('apps.accounts.services.UserService.activate_users')
    def test_bulk_user_operation_task_activate(self, mock_activate):
        """Test bulk_user_operation_task for activation."""
        user_ids = [1, 2, 3]
        mock_activate.return_value = {'activated': 3}
        
        result = bulk_user_operation_task('activate', user_ids, self.user.id)
        
        mock_activate.assert_called_once_with(user_ids)
        self.assertEqual(result['activated'], 3)


# ============================================================================
# Integration Tests
# ============================================================================

class IntegrationTests(TransactionTestCase):
    """
    Integration tests for complete workflows.
    """
    
    def setUp(self):
        self.client = Client()
        self.admin_user = UserFactory.create_superuser(
            email='admin@example.com',
            password='adminpass123'
        )
    
    def test_complete_user_lifecycle(self):
        """Test complete user lifecycle from creation to deletion."""
        # Login as admin
        self.client.login(email='admin@example.com', password='adminpass123')
        
        # Create user
        create_data = {
            'email': 'lifecycle@example.com',
            'first_name': 'Lifecycle',
            'last_name': 'User',
            'password1': 'complexpass123',
            'password2': 'complexpass123',
        }
        
        response = self.client.post(reverse('accounts:user_create'), data=create_data)
        self.assertEqual(response.status_code, 302)
        
        user = User.objects.get(email='lifecycle@example.com')
        self.assertTrue(user.is_active)
        
        # Update user
        update_data = {
            'first_name': 'Updated',
            'last_name': 'Lifecycle',
            'email': 'lifecycle@example.com',
        }
        
        response = self.client.post(
            reverse('accounts:user_update', kwargs={'pk': user.pk}),
            data=update_data
        )
        self.assertEqual(response.status_code, 302)
        
        user.refresh_from_db()
        self.assertEqual(user.first_name, 'Updated')
        
        # Deactivate user via AJAX
        response = self.client.post(
            reverse('accounts:ajax_toggle_status', kwargs={'pk': user.pk})
        )
        self.assertEqual(response.status_code, 200)
        
        user.refresh_from_db()
        self.assertFalse(user.is_active)
        
        # Delete user
        response = self.client.post(
            reverse('accounts:user_delete', kwargs={'pk': user.pk})
        )
        self.assertEqual(response.status_code, 302)
        
        self.assertFalse(User.objects.filter(id=user.id).exists())
    
    def test_bulk_operations_workflow(self):
        """Test bulk operations workflow."""
        # Create multiple users
        users = [UserFactory.create_user() for _ in range(5)]
        user_ids = [str(user.id) for user in users]
        
        # Login as admin
        self.client.login(email='admin@example.com', password='adminpass123')
        
        # Perform bulk deactivation
        bulk_data = {
            'action': 'deactivate',
            'user_ids': ','.join(user_ids),
        }
        
        response = self.client.post(reverse('accounts:bulk_action'), data=bulk_data)
        self.assertEqual(response.status_code, 302)
        
        # Note: In real scenario, this would be processed asynchronously
        # For testing, we can check that the task was initiated
        
        # Check that activity was logged
        activity = Activity.objects.filter(
            action='bulk_user_action',
            user=self.admin_user
        ).first()
        
        self.assertIsNotNone(activity)
        self.assertIn('bulk deactivate', activity.description)


# ============================================================================
# Performance Tests
# ============================================================================

class PerformanceTests(TestCase):
    """
    Performance tests for accounts app.
    """
    
    def setUp(self):
        # Create a large number of users for performance testing
        self.users = [UserFactory.create_user() for _ in range(100)]
    
    def test_user_list_performance(self):
        """Test performance of user list view with many users."""
        admin_user = UserFactory.create_superuser()
        
        client = Client()
        client.force_login(admin_user)
        
        # Measure time for user list view
        import time
        start_time = time.time()
        
        response = client.get(reverse('accounts:user_list'))
        
        end_time = time.time()
        execution_time = end_time - start_time
        
        self.assertEqual(response.status_code, 200)
        # Assert that the view loads within reasonable time (adjust as needed)
        self.assertLess(execution_time, 2.0)  # 2 seconds
    
    def test_user_search_performance(self):
        """Test performance of user search."""
        admin_user = UserFactory.create_superuser()
        
        client = Client()
        client.force_login(admin_user)
        
        # Measure time for search
        import time
        start_time = time.time()
        
        response = client.get(
            reverse('accounts:ajax_search'),
            {'q': 'test'}
        )
        
        end_time = time.time()
        execution_time = end_time - start_time
        
        self.assertEqual(response.status_code, 200)
        # Assert that search completes within reasonable time
        self.assertLess(execution_time, 1.0)  # 1 second


# ============================================================================
# Security Tests
# ============================================================================

class SecurityTests(TestCase):
    """
    Security tests for accounts app.
    """
    
    def setUp(self):
        self.user = UserFactory.create_user(
            email='user@example.com',
            password='userpass123'
        )
        self.admin_user = UserFactory.create_superuser(
            email='admin@example.com',
            password='adminpass123'
        )
    
    def test_unauthorized_access_to_admin_views(self):
        """Test that regular users cannot access admin views."""
        client = Client()
        client.login(email='user@example.com', password='userpass123')
        
        # Try to access admin views
        admin_urls = [
            reverse('accounts:user_admin'),
            reverse('accounts:user_statistics'),
            reverse('accounts:user_create'),
        ]
        
        for url in admin_urls:
            response = client.get(url)
            # Should be forbidden or redirect
            self.assertIn(response.status_code, [302, 403])
    
    def test_user_can_only_edit_own_profile(self):
        """Test that users can only edit their own profile."""
        other_user = UserFactory.create_user(email='other@example.com')
        
        client = Client()
        client.login(email='user@example.com', password='userpass123')
        
        # Try to edit other user's profile
        response = client.get(
            reverse('accounts:user_update', kwargs={'pk': other_user.pk})
        )
        
        # Should be forbidden or redirect
        self.assertIn(response.status_code, [302, 403])
    
    def test_password_validation(self):
        """Test password validation requirements."""
        weak_passwords = [
            '123',
            'password',
            '12345678',
            'qwerty',
        ]
        
        for weak_password in weak_passwords:
            form_data = {
                'email': 'test@example.com',
                'first_name': 'Test',
                'last_name': 'User',
                'password1': weak_password,
                'password2': weak_password,
            }
            
            form = UserCreationForm(data=form_data)
            self.assertFalse(form.is_valid())
    
    def test_email_injection_protection(self):
        """Test protection against email injection attacks."""
        malicious_emails = [
            'test@example.com\nBcc: attacker@evil.com',
            'test@example.com\r\nBcc: attacker@evil.com',
            'test@example.com%0ABcc: attacker@evil.com',
        ]
        
        for malicious_email in malicious_emails:
            form_data = {
                'email': malicious_email,
                'first_name': 'Test',
                'last_name': 'User',
                'password1': 'complexpass123',
                'password2': 'complexpass123',
            }
            
            form = UserCreationForm(data=form_data)
            self.assertFalse(form.is_valid())
    
    def test_csrf_protection(self):
        """Test CSRF protection on forms."""
        client = Client(enforce_csrf_checks=True)
        client.login(email='admin@example.com', password='adminpass123')
        
        form_data = {
            'email': 'newuser@example.com',
            'first_name': 'New',
            'last_name': 'User',
            'password1': 'complexpass123',
            'password2': 'complexpass123',
        }
        
        # POST without CSRF token should fail
        response = client.post(reverse('accounts:user_create'), data=form_data)
        self.assertEqual(response.status_code, 403)
    
    def test_sql_injection_protection(self):
        """Test protection against SQL injection in search."""
        admin_user = UserFactory.create_superuser()
        
        client = Client()
        client.force_login(admin_user)
        
        # Try SQL injection in search
        malicious_queries = [
            "'; DROP TABLE accounts_user; --",
            "' OR '1'='1",
            "'; UPDATE accounts_user SET is_superuser=1; --",
        ]
        
        for query in malicious_queries:
            response = client.get(
                reverse('accounts:user_list'),
                {'search': query}
            )
            
            # Should not cause server error
            self.assertEqual(response.status_code, 200)
            
            # Database should still be intact
            self.assertTrue(User.objects.exists())


# ============================================================================
# Test Runner Configuration
# ============================================================================

class AccountsTestSuite:
    """
    Test suite configuration for accounts app.
    """
    
    @classmethod
    def get_test_classes(cls):
        """Get all test classes for the accounts app."""
        return [
            UserModelTests,
            UserFormTests,
            UserViewTests,
            AjaxViewTests,
            UserAPITests,
            UserSerializerTests,
            UserServiceTests,
            AuthenticationServiceTests,
            ProfileServiceTests,
            ExportServiceTests,
            TaskTests,
            IntegrationTests,
            PerformanceTests,
            SecurityTests,
        ]
    
    @classmethod
    def run_all_tests(cls):
        """
        Run all tests for the accounts app.
        """
        from django.test.utils import get_runner
        from django.conf import settings
        
        TestRunner = get_runner(settings)
        test_runner = TestRunner()
        
        test_classes = cls.get_test_classes()
        failures = test_runner.run_tests(test_classes)
        
        return failures == 0