"""
Тесты производительности для API домашних заданий.
Измеряют время ответа и количество SQL запросов.
"""
import time
import pytest
from django.test.utils import override_settings
from django.db import connection, reset_queries
from django.contrib.auth import get_user_model

User = get_user_model()


@pytest.mark.django_db
@pytest.mark.performance
class TestHomeworkPerformance:
    """Тесты производительности API домашних заданий."""
    
    @pytest.fixture
    def setup_data(self, mentor_user, client_user):
        """Создает тестовые данные для проверки производительности."""
        from apps.schedule.models import Lesson
        from apps.homework.models import Homework, HomeworkSubmission
        
        # Создаем несколько студентов
        students = []
        for i in range(10):
            student = User.objects.create_user(
                email=f'student{i}@test.com',
                password='TestPass123!',
                first_name=f'Студент{i}',
                last_name=f'Тестовый{i}',
                role='client',
                is_email_verified=True,
                is_active=True
            )
            students.append(student)
        
        # Создаем занятие
        lesson = Lesson.objects.create(
            mentor=mentor_user,
            title='Тестовое занятие',
            status='scheduled'
        )
        
        # Создаем домашние задания
        homeworks = []
        for i in range(5):
            homework = Homework.objects.create(
                title=f'ДЗ {i+1}',
                description=f'Описание ДЗ {i+1}',
                mentor=mentor_user,
                lesson=lesson,
                status='published',
                max_score=100
            )
            # Назначаем студентов
            homework.assigned_to.set(students)
            
            # Создаем решения для некоторых студентов
            for j, student in enumerate(students[:5]):  # 5 студентов сдали
                HomeworkSubmission.objects.create(
                    homework=homework,
                    student=student,
                    content=f'Решение от студента {j}',
                    status='graded' if j % 2 == 0 else 'pending',
                    score=80 + j if j % 2 == 0 else None
                )
            
            homeworks.append(homework)
        
        return {
            'mentor_user': mentor_user,
            'students': students,
            'homeworks': homeworks
        }
    
    def test_homework_list_performance_mentor(self, authenticated_client):
        """Тест производительности списка ДЗ для ментора."""
        reset_queries()
        start_time = time.time()
        
        response = authenticated_client.get('/api/homework/homeworks/')
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        query_count = len(connection.queries)
        
        assert response.status_code == 200
        assert elapsed_time < 0.5, f"Время ответа слишком долгое: {elapsed_time:.3f}с"
        assert query_count < 20, f"Слишком много SQL запросов: {query_count}"
        
        print(f"\n📊 Список ДЗ (ментор):")
        print(f"   Время: {elapsed_time:.3f}с")
        print(f"   SQL запросов: {query_count}")
        print(f"   ДЗ в ответе: {len(response.json().get('results', response.json()))}")
    
    def test_homework_list_performance_student(self, authenticated_client_user):
        """Тест производительности списка ДЗ для студента."""
        reset_queries()
        start_time = time.time()
        
        response = authenticated_client_user.get('/api/homework/homeworks/')
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        query_count = len(connection.queries)
        
        assert response.status_code == 200
        assert elapsed_time < 0.3, f"Время ответа слишком долгое: {elapsed_time:.3f}с"
        assert query_count < 15, f"Слишком много SQL запросов: {query_count}"
        
        print(f"\n📊 Список ДЗ (студент):")
        print(f"   Время: {elapsed_time:.3f}с")
        print(f"   SQL запросов: {query_count}")
    
    def test_homework_statistics_performance(self, authenticated_client, setup_data):
        """Тест производительности статистики ДЗ."""
        homework = setup_data['homeworks'][0]
        reset_queries()
        start_time = time.time()
        
        response = authenticated_client.get(f'/api/homework/homeworks/{homework.id}/statistics/')
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        query_count = len(connection.queries)
        
        assert response.status_code == 200
        assert elapsed_time < 0.2, f"Время ответа слишком долгое: {elapsed_time:.3f}с"
        assert query_count < 5, f"Слишком много SQL запросов: {query_count}"
        
        print(f"\n📊 Статистика ДЗ:")
        print(f"   Время: {elapsed_time:.3f}с")
        print(f"   SQL запросов: {query_count}")
        print(f"   Данные: {response.json()}")
    
    def test_homework_submissions_list_performance(self, authenticated_client, setup_data):
        """Тест производительности списка решений ДЗ."""
        homework = setup_data['homeworks'][0]
        reset_queries()
        start_time = time.time()
        
        response = authenticated_client.get(
            f'/api/homework/submissions/?homework_id={homework.id}'
        )
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        query_count = len(connection.queries)
        
        assert response.status_code == 200
        assert elapsed_time < 0.3, f"Время ответа слишком долгое: {elapsed_time:.3f}с"
        assert query_count < 10, f"Слишком много SQL запросов: {query_count}"
        
        print(f"\n📊 Список решений ДЗ:")
        print(f"   Время: {elapsed_time:.3f}с")
        print(f"   SQL запросов: {query_count}")
        print(f"   Решений в ответе: {len(response.json().get('results', response.json()))}")


@pytest.mark.django_db
@pytest.mark.performance
class TestChatPerformance:
    """Тесты производительности API чата."""
    
    @pytest.fixture
    def setup_chat_data(self, mentor_user, client_user):
        """Создает тестовые данные для чата."""
        from apps.chat.models import Chat, ChatParticipant, Message, MessageRead
        
        # Создаем несколько пользователей
        users = [mentor_user, client_user]
        for i in range(5):
            user = User.objects.create_user(
                email=f'user{i}@test.com',
                password='TestPass123!',
                first_name=f'Пользователь{i}',
                last_name=f'Тестовый{i}',
                role='client',
                is_email_verified=True,
                is_active=True
            )
            users.append(user)
        
        # Создаем чаты с участниками и сообщениями
        chats = []
        for i in range(3):
            chat = Chat.objects.create(
                chat_type='group',
                name=f'Чат {i+1}',
                created_by=mentor_user
            )
            
            # Добавляем участников
            for user in users[:3]:
                ChatParticipant.objects.create(
                    chat=chat,
                    user=user,
                    role='member'
                )
            
            # Создаем сообщения
            for j in range(10):
                message = Message.objects.create(
                    chat=chat,
                    sender=users[j % len(users)],
                    content=f'Сообщение {j+1} в чате {i+1}'
                )
                
                # Помечаем некоторые сообщения как прочитанные
                if j % 2 == 0:
                    MessageRead.objects.create(
                        message=message,
                        user=mentor_user
                    )
            
            chats.append(chat)
        
        return {
            'mentor_user': mentor_user,
            'chats': chats
        }
    
    def test_chat_list_performance(self, authenticated_client):
        """Тест производительности списка чатов."""
        reset_queries()
        start_time = time.time()
        
        response = authenticated_client.get('/api/chat/chats/')
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        query_count = len(connection.queries)
        
        assert response.status_code == 200
        assert elapsed_time < 0.4, f"Время ответа слишком долгое: {elapsed_time:.3f}с"
        assert query_count < 15, f"Слишком много SQL запросов: {query_count}"
        
        print(f"\n📊 Список чатов:")
        print(f"   Время: {elapsed_time:.3f}с")
        print(f"   SQL запросов: {query_count}")
        print(f"   Чатов в ответе: {len(response.json().get('results', response.json()))}")
    
    def test_chat_messages_performance(self, authenticated_client, setup_chat_data):
        """Тест производительности сообщений чата."""
        chat = setup_chat_data['chats'][0]
        reset_queries()
        start_time = time.time()
        
        response = authenticated_client.get(f'/api/chat/chats/{chat.uuid}/messages/')
        
        end_time = time.time()
        elapsed_time = end_time - start_time
        query_count = len(connection.queries)
        
        assert response.status_code == 200
        assert elapsed_time < 0.3, f"Время ответа слишком долгое: {elapsed_time:.3f}с"
        assert query_count < 10, f"Слишком много SQL запросов: {query_count}"
        
        print(f"\n📊 Сообщения чата:")
        print(f"   Время: {elapsed_time:.3f}с")
        print(f"   SQL запросов: {query_count}")
        messages_data = response.json().get('results', response.json())
        print(f"   Сообщений в ответе: {len(messages_data)}")


@pytest.mark.django_db
@pytest.mark.performance
class TestGeneralPerformance:
    """Общие тесты производительности."""
    
    def test_multiple_requests_performance(self, authenticated_client):
        """Тест производительности при множественных запросах."""
        times = []
        query_counts = []
        
        for i in range(5):
            reset_queries()
            start_time = time.time()
            
            response = authenticated_client.get('/api/homework/homeworks/')
            
            end_time = time.time()
            times.append(end_time - start_time)
            query_counts.append(len(connection.queries))
            
            assert response.status_code == 200
        
        avg_time = sum(times) / len(times)
        avg_queries = sum(query_counts) / len(query_counts)
        max_time = max(times)
        max_queries = max(query_counts)
        
        print(f"\n📊 Множественные запросы (5 раз):")
        print(f"   Среднее время: {avg_time:.3f}с")
        print(f"   Максимальное время: {max_time:.3f}с")
        print(f"   Среднее SQL запросов: {avg_queries:.1f}")
        print(f"   Максимум SQL запросов: {max_queries}")
        
        assert avg_time < 0.5, f"Среднее время слишком долгое: {avg_time:.3f}с"
        assert avg_queries < 20, f"Среднее количество запросов слишком большое: {avg_queries:.1f}"

