"""
API views для домашних заданий.
"""
import logging
import html
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from django.db import models
from django.utils import timezone
from .models import Homework, HomeworkSubmission, HomeworkFile, HomeworkAIAgent
from .serializers import (
    HomeworkSerializer,
    HomeworkListSerializer,
    HomeworkCreateSerializer,
    HomeworkSubmissionSerializer,
    HomeworkSubmissionCreateSerializer,
    HomeworkGradeSerializer,
    HomeworkReturnSerializer,
    HomeworkFileSerializer,
    HomeworkAIAgentSerializer,
)
from .permissions import IsHomeworkMentor, IsSubmissionOwnerOrMentor
from django.contrib.auth import get_user_model
from config.throttling import UploadRateThrottle

User = get_user_model()

logger = logging.getLogger(__name__)


def _student_display_name(submission):
    """Имя ученика (только имя, без фамилии) — тот, кто отправил ДЗ."""
    if not submission or not getattr(submission, 'student', None):
        return None
    s = submission.student
    name = (s.first_name or (s.get_short_name() if getattr(s, 'email', None) else '') or '').strip()
    return name or f"Студент (id: {s.pk})"


class HomeworkViewSet(viewsets.ModelViewSet):
    """
    ViewSet для управления домашними заданиями.
    
    list: Список ДЗ
    create: Создать ДЗ
    retrieve: Получить ДЗ
    update: Обновить ДЗ
    destroy: Удалить ДЗ
    publish: Опубликовать ДЗ
    archive: Архивировать ДЗ
    statistics: Статистика ДЗ
    """
    
    permission_classes = [IsAuthenticated]
    
    def get_throttles(self):
        """Применяем throttling только для создания (загрузки файлов)."""
        if self.action == 'create':
            return [UploadRateThrottle()]
        return super().get_throttles()
    
    def get_permissions(self):
        """Определение прав доступа для разных действий."""
        if self.action in ['update', 'partial_update', 'destroy']:
            return [IsAuthenticated(), IsHomeworkMentor()]
        return [IsAuthenticated()]
    
    def get_queryset(self):
        """Получение ДЗ."""
        user = self.request.user
        filter_status = self.request.query_params.get('status')
        
        if user.role == 'mentor':
            # Ментор видит свои задания
            queryset = Homework.objects.filter(
                mentor=user
            ).select_related('mentor', 'lesson').prefetch_related(
                'assigned_to',
                'submissions__student',
                'files',
                'assignment_files'  # Файлы задания (прямая связь)
            )
        elif user.role == 'parent':
            # Родитель видит задания своих детей
            from apps.users.models import Parent, Client
            try:
                parent = Parent.objects.get(user=user)
                children_ids = parent.children.values_list('user_id', flat=True)
                
                # Если указан child_id (user_id ребенка), фильтруем по конкретному ребенку
                child_id = self.request.query_params.get('child_id')
                if child_id:
                    try:
                        # Проверяем, что это ребенок родителя
                        child_client = Client.objects.get(user_id=child_id)
                        if child_client.id in parent.children.values_list('id', flat=True):
                            # Фильтруем задания, назначенные этому ребенку
                            queryset = Homework.objects.filter(
                                assigned_to=child_client.user,
                                status='published'
                            ).select_related('mentor', 'lesson').prefetch_related(
                                'assigned_to',
                                'submissions__student',
                                'files',
                                'assignment_files'
                            )
                        else:
                            queryset = Homework.objects.none()
                    except (Client.DoesNotExist, ValueError):
                        queryset = Homework.objects.none()
                else:
                    # Если child_id не указан, показываем задания всех детей
                    queryset = Homework.objects.filter(
                        assigned_to__id__in=children_ids,
                        status='published'
                    ).select_related('mentor', 'lesson').prefetch_related(
                        'assigned_to',
                        'submissions__student',
                        'files',
                        'assignment_files'
                    ).distinct()
            except Parent.DoesNotExist:
                queryset = Homework.objects.none()
        else:
            # Студент видит назначенные ему задания
            queryset = Homework.objects.filter(
                assigned_to=user,
                status='published'
            ).select_related('mentor', 'lesson').prefetch_related(
                'assigned_to',
                'submissions__student',
                'files',
                'assignment_files'  # Файлы задания (прямая связь)
            )
        
        # Оптимизация: для списка используем only() для ограничения полей
        if self.action == 'list':
            queryset = queryset.only(
                'id', 'title', 'description', 'mentor_id', 'lesson_id',
                'deadline', 'max_score', 'passing_score', 'status', 'fill_later',
                'total_submissions', 'checked_submissions', 'returned_submissions',
                'ai_draft_submissions', 'average_score',
                'created_at', 'updated_at', 'published_at'
            )
        
        # Фильтрация по статусу submissions
        if filter_status:
            if filter_status == 'pending':
                # Ожидают: нет решений или все решения в статусе pending
                if user.role == 'mentor':
                    # Для ментора: задания, где нет решений вообще
                    queryset = queryset.filter(
                        submissions__isnull=True
                    ).distinct()
                else:
                    # Для студента: задания без его решений
                    queryset = queryset.exclude(
                        submissions__student=user
                    ).distinct()
            elif filter_status == 'submitted':
                # На проверке: есть решения в статусе checking или pending (но не graded)
                if user.role == 'mentor':
                    # Для ментора: задания с решениями в статусе checking или pending
                    queryset = queryset.filter(
                        submissions__status__in=['checking', 'pending']
                    ).exclude(
                        submissions__status='graded'
                    ).distinct()
                else:
                    # Для студента: его решения в статусе checking или pending
                    queryset = queryset.filter(
                        submissions__student=user,
                        submissions__status__in=['checking', 'pending']
                    ).distinct()
            elif filter_status == 'reviewed':
                # Проверено: есть решения в статусе graded
                if user.role == 'mentor':
                    # Для ментора: задания с хотя бы одним решением в статусе graded
                    queryset = queryset.filter(
                        submissions__status='graded'
                    ).distinct()
                else:
                    # Для студента: его решения в статусе graded
                    queryset = queryset.filter(
                        submissions__student=user,
                        submissions__status='graded'
                    ).distinct()
        
        return queryset
    
    def get_serializer_class(self):
        """Выбор сериализатора."""
        if self.action == 'list':
            return HomeworkListSerializer
        elif self.action == 'create':
            return HomeworkCreateSerializer
        elif self.action in ['update', 'partial_update']:
            return HomeworkCreateSerializer  # Используем тот же сериализатор для обновления
        return HomeworkSerializer
    
    def create(self, request, *args, **kwargs):
        """Создание ДЗ."""
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        homework = serializer.save()
        
        # Инвалидируем кеш дашборда после создания ДЗ
        from apps.users.cache_utils import invalidate_dashboard_cache
        invalidate_dashboard_cache(homework.mentor.id, 'mentor')
        students = list(homework.assigned_to.all())
        for student in students:
            invalidate_dashboard_cache(student.id, 'client')
        
        # Отправляем уведомление о новом ДЗ только если НЕ отложенное
        if not homework.fill_later:
            from apps.notifications.services import NotificationService
            NotificationService.send_homework_notification(homework, 'homework_assigned')
        
        response_serializer = HomeworkSerializer(homework)
        return Response(
            response_serializer.data,
            status=status.HTTP_201_CREATED
        )
    
    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        """
        Опубликовать ДЗ.
        
        POST /api/homework/homeworks/{id}/publish/
        
        Также используется для публикации отложенных ДЗ (fill_later=True).
        При публикации сбрасывается флаг fill_later.
        """
        homework = self.get_object()
        
        # Проверяем права
        if homework.mentor != request.user:
            return Response(
                {'error': 'Только автор может опубликовать задание'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Запоминаем был ли это отложенный ДЗ (для отправки уведомления)
        was_fill_later = homework.fill_later
        
        # Сбрасываем fill_later при публикации
        if homework.fill_later:
            homework.fill_later = False
            homework.save(update_fields=['fill_later'])
        
        homework.publish()
        
        # Инвалидируем кеш дашборда после публикации ДЗ
        from apps.users.cache_utils import invalidate_dashboard_cache
        invalidate_dashboard_cache(homework.mentor.id, 'mentor')
        students = list(homework.assigned_to.all())
        for student in students:
            invalidate_dashboard_cache(student.id, 'client')
        
        # Отправляем уведомления студентам
        from apps.notifications.services import NotificationService
        for student in students:
            NotificationService.create_notification_with_telegram(
                recipient=student,
                notification_type='homework_assigned',
                title='📚 Новое домашнее задание',
                message=f'Новое домашнее задание: "{homework.title}"',
                priority='normal',
                action_url=f'/homework/{homework.id}/',
                content_object=homework
            )
        
        serializer = HomeworkSerializer(homework)
        response_data = serializer.data
        if was_fill_later:
            response_data['was_fill_later'] = True
        return Response(response_data)
    
    @action(detail=True, methods=['post'])
    def archive(self, request, pk=None):
        """
        Архивировать ДЗ.
        
        POST /api/homework/homeworks/{id}/archive/
        """
        homework = self.get_object()
        
        # Проверяем права
        if homework.mentor != request.user:
            return Response(
                {'error': 'Только автор может архивировать задание'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        homework.archive()
        
        serializer = HomeworkSerializer(homework)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def fill_later_list(self, request):
        """
        Получить список отложенных ДЗ (fill_later=True) для ментора.
        
        GET /api/homework/homeworks/fill_later_list/
        
        Возвращает ДЗ, которые были созданы с флагом "заполнить позже"
        и ожидают заполнения ментором.
        """
        if request.user.role != 'mentor':
            return Response(
                {'error': 'Только ментор может просматривать отложенные ДЗ'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        queryset = Homework.objects.filter(
            mentor=request.user,
            fill_later=True
        ).select_related('mentor', 'lesson', 'lesson__client', 'lesson__client__user').prefetch_related(
            'assigned_to'
        ).order_by('-created_at')
        
        serializer = HomeworkListSerializer(queryset, many=True, context={'request': request})
        return Response({
            'count': queryset.count(),
            'results': serializer.data
        })
    
    @action(detail=True, methods=['get'])
    def statistics(self, request, pk=None):
        """
        Получить статистику ДЗ.
        
        GET /api/homework/homeworks/{id}/statistics/
        """
        homework = self.get_object()
        
        # Проверяем права
        if homework.mentor != request.user:
            return Response(
                {'error': 'Только автор может просмотреть статистику'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Оптимизация: используем один запрос с агрегацией вместо множества отдельных count()
        from django.db.models import Count, Q, Avg
        
        submissions_queryset = homework.submissions.all()
        
        # Получаем все подсчеты одним запросом через агрегацию
        aggregated = submissions_queryset.aggregate(
            total_submissions=Count('id'),
            unique_students=Count('student', distinct=True),
            pending=Count('id', filter=Q(status='pending')),
            checking=Count('id', filter=Q(status='checking')),
            graded=Count('id', filter=Q(status='graded')),
            returned=Count('id', filter=Q(status='returned')),
            passed=Count('id', filter=Q(passed=True)),
            failed=Count('id', filter=Q(passed=False, status='graded')),
            on_time=Count('id', filter=Q(is_late=False)),
            late=Count('id', filter=Q(is_late=True)),
        )
        
        # Оптимизация: используем count() только один раз
        total_assigned = homework.assigned_to.count()
        
        stats = {
            'total_assigned': total_assigned,
            'total_submissions': aggregated['total_submissions'],
            'unique_students': aggregated['unique_students'],
            'pending': aggregated['pending'],
            'checking': aggregated['checking'],
            'graded': aggregated['graded'],
            'returned': aggregated['returned'],
            'passed': aggregated['passed'],
            'failed': aggregated['failed'],
            'average_score': homework.average_score,
            'on_time': aggregated['on_time'],
            'late': aggregated['late'],
        }
        
        # Распределение баллов - оптимизируем через один запрос с фильтрацией
        graded_submissions = submissions_queryset.filter(status='graded').values_list('score', flat=True)
        if graded_submissions.exists():
            score_distribution = []
            # Получаем все оценки одним запросом и считаем в Python
            scores = list(graded_submissions)
            for i in range(0, homework.max_score + 1, 10):
                count = sum(1 for score in scores if score is not None and i <= score < i + 10)
                score_distribution.append({
                    'range': f'{i}-{i+9}',
                    'count': count
                })
            stats['score_distribution'] = score_distribution
        
        return Response(stats)
    
    @action(detail=False, methods=['get'])
    def my_homeworks(self, request):
        """
        Мои домашние задания (для студентов).
        
        GET /api/homework/homeworks/my_homeworks/
        """
        user = request.user
        homeworks = Homework.objects.filter(
            assigned_to=user,
            status='published'
        ).select_related('mentor', 'lesson').prefetch_related(
            'assigned_to',
            'submissions__student'
        ).only(
            'id', 'title', 'description', 'mentor_id', 'lesson_id',
            'deadline', 'max_score', 'passing_score', 'status', 'fill_later',
            'total_submissions', 'checked_submissions', 'average_score',
            'created_at', 'updated_at', 'published_at'
        )
        
        serializer = HomeworkListSerializer(homeworks, many=True, context={'request': request})
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def created_by_me(self, request):
        """
        Созданные мной задания (для менторов).
        
        GET /api/homework/homeworks/created_by_me/
        """
        homeworks = Homework.objects.filter(
            mentor=request.user
        ).select_related('mentor', 'lesson').prefetch_related(
            'assigned_to',
            'submissions__student'
        ).only(
            'id', 'title', 'description', 'mentor_id', 'lesson_id',
            'deadline', 'max_score', 'passing_score', 'status', 'fill_later',
            'total_submissions', 'checked_submissions', 'average_score',
            'created_at', 'updated_at', 'published_at'
        )
        
        serializer = HomeworkListSerializer(homeworks, many=True, context={'request': request})
        return Response(serializer.data)


class HomeworkSubmissionViewSet(viewsets.ModelViewSet):
    """
    ViewSet для управления решениями ДЗ.
    
    list: Список решений
    create: Создать решение
    retrieve: Получить решение
    update: Обновить решение
    destroy: Удалить решение
    grade: Выставить оценку
    return_for_revision: Вернуть на доработку
    """
    
    permission_classes = [IsAuthenticated, IsSubmissionOwnerOrMentor]
    
    def get_queryset(self):
        """Получение решений."""
        user = self.request.user
        homework_id = self.request.query_params.get('homework_id')
        child_id = self.request.query_params.get('child_id')
        
        queryset = HomeworkSubmission.objects.all()
        
        # Оптимизация: для списка используем только select_related для необходимых полей
        # и only() для ограничения полей (но без конфликтующих полей)
        if self.action == 'list':
            queryset = queryset.select_related(
                'homework',
                'homework__mentor',
                'student'
            ).prefetch_related('files').only(
                'id', 'homework_id', 'student_id', 'checked_by_id', 'status', 'score',
                'passed', 'is_late', 'submitted_at', 'checked_at', 'feedback',
                'updated_at'
            )
        else:
            # Для детального просмотра используем полный select_related
            queryset = queryset.select_related(
                'homework',
                'homework__mentor',
                'student',
                'checked_by'
            ).prefetch_related('files')
        
        # Фильтр по заданию
        if homework_id:
            queryset = queryset.filter(homework_id=homework_id)
        
        # Ментор видит решения своих заданий
        if user.role == 'mentor':
            queryset = queryset.filter(homework__mentor=user)
        elif user.role == 'parent' and child_id:
            # Родитель с child_id видит решения выбранного ребёнка
            try:
                from apps.users.models import Client, Parent
                parent_profile = Parent.objects.get(user=user)
                child_client = Client.objects.get(user_id=child_id)
                if child_client in parent_profile.children.all():
                    queryset = queryset.filter(student=child_client.user)
                else:
                    queryset = queryset.none()
            except (Client.DoesNotExist, Parent.DoesNotExist, ValueError):
                queryset = queryset.none()
        else:
            # Студент видит только свои решения
            queryset = queryset.filter(student=user)
        
        return queryset
    
    def get_serializer_class(self):
        """Выбор сериализатора."""
        if self.action == 'create':
            return HomeworkSubmissionCreateSerializer
        elif self.action == 'grade':
            return HomeworkGradeSerializer
        elif self.action == 'return_for_revision':
            return HomeworkReturnSerializer
        return HomeworkSubmissionSerializer
    
    def create(self, request, *args, **kwargs):
        """Создание решения."""
        # Получаем все файлы из запроса (может быть несколько с одинаковым именем поля)
        files = request.FILES.getlist('attachment')
        
        # Для сериализатора оставляем только первый файл (если есть)
        # Остальные обработаем после создания submission
        if files:
            request.data._mutable = True
            request.data['attachment'] = files[0]
            request.data._mutable = False
        
        # Проверяем, есть ли submission со статусом 'returned' для обновления
        homework_id = request.data.get('homework_id')
        from .models import HomeworkSubmission, HomeworkFile
        returned_submission_id = None
        if homework_id:
            try:
                returned_submission = HomeworkSubmission.objects.filter(
                    homework_id=homework_id,
                    student=request.user,
                    status='returned'
                ).order_by('-submitted_at').first()
                if returned_submission:
                    returned_submission_id = returned_submission.id
            except:
                pass
        
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        submission = serializer.save()
        
        # Если обновляется существующее submission (было возвращено на доработку),
        # удаляем старые дополнительные файлы
        if returned_submission_id and submission.id == returned_submission_id:
            old_files = HomeworkFile.objects.filter(
                submission=submission,
                file_type='submission'
            )
            if old_files.exists():
                # Удаляем старые файлы при перезаписи submission
                old_files.delete()
        
        # Сохраняем остальные файлы как HomeworkFile
        if len(files) > 1:
            for file in files[1:]:
                HomeworkFile.objects.create(
                    submission=submission,
                    file_type='submission',
                    file=file,
                    filename=file.name,
                    file_size=file.size,
                    uploaded_by=request.user
                )
        
        # Инвалидируем кеш дашборда после создания решения ДЗ
        from apps.users.cache_utils import invalidate_dashboard_cache
        invalidate_dashboard_cache(submission.student.id, 'client')
        invalidate_dashboard_cache(submission.homework.mentor.id, 'mentor')
        
        # Отправляем уведомление ментору
        from apps.notifications.services import NotificationService
        NotificationService.create_notification_with_telegram(
            recipient=submission.homework.mentor,
            notification_type='homework_submitted',
            title='📝 ДЗ сдано',
            message=f'{submission.student.get_full_name()} сдал ДЗ "{submission.homework.title}"',
            priority='normal',
            action_url=f'/homework/{submission.homework.id}/submissions/{submission.id}/',
            content_object=submission
        )
        
        # По настройкам ментора: доверять AI — запускаем проверку (черновик или публикация)
        mentor = submission.homework.mentor
        mentor.refresh_from_db(fields=['ai_trust_draft', 'ai_trust_publish'])
        if getattr(mentor, 'ai_trust_publish', False):
            from .tasks import run_mentor_ai_check_submission
            logger.info(
                "ДЗ: запуск AI проверки (публикация) для submission_id=%s, mentor_id=%s",
                submission.id, mentor.id
            )
            run_mentor_ai_check_submission.delay(submission.id, publish=True)
        elif getattr(mentor, 'ai_trust_draft', False):
            from .tasks import run_mentor_ai_check_submission
            logger.info(
                "ДЗ: запуск AI проверки (черновик) для submission_id=%s, mentor_id=%s",
                submission.id, mentor.id
            )
            run_mentor_ai_check_submission.delay(submission.id, publish=False)
        
        response_serializer = HomeworkSubmissionSerializer(submission)
        return Response(
            response_serializer.data,
            status=status.HTTP_201_CREATED
        )
    
    @action(detail=True, methods=['post'])
    def check_with_ai(self, request, pk=None):
        """
        Проверить решение через AI.
        
        POST /api/homework/submissions/{id}/check_with_ai/
        """
        submission = self.get_object()
        
        # Проверяем права доступа (только ментор)
        if request.user.role != 'mentor':
            return Response(
                {'error': 'Только ментор может использовать AI проверку'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Проверяем что это задание ментора
        if submission.homework.mentor != request.user:
            return Response(
                {'error': 'Вы не можете проверять это задание'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Импортируем сервис
        from .ai_service import get_ai_service
        from django.core.files.storage import default_storage
        
        # Файлы задания: имена, пути (если есть), содержимое (если path недоступен — S3 и т.д.)
        homework_files = []
        homework_file_paths = []
        homework_file_contents = []
        def _add_homework_file(name):
            homework_files.append(name)
            path_ok = False
            try:
                p = default_storage.path(name)
                if p:
                    homework_file_paths.append(p)
                    path_ok = True
            except Exception:
                pass
            if not path_ok:
                try:
                    with default_storage.open(name, 'rb') as f:
                        data = f.read(2 * 1024 * 1024 + 1)  # лимит 2 МБ
                    fname = name.split('/')[-1] if '/' in name else name
                    homework_file_contents.append((fname, data[: 2 * 1024 * 1024]))
                except Exception:
                    pass
        if submission.homework.attachment:
            _add_homework_file(submission.homework.attachment.name)
        for f in submission.homework.assignment_files.all():
            if f.file:
                _add_homework_file(f.file.name)
        # Файлы решения
        submission_files = []
        submission_file_paths = []
        submission_file_contents = []
        def _add_submission_file(name):
            submission_files.append(name)
            path_ok = False
            try:
                p = default_storage.path(name)
                if p:
                    submission_file_paths.append(p)
                    path_ok = True
            except Exception:
                pass
            if not path_ok:
                try:
                    with default_storage.open(name, 'rb') as f:
                        data = f.read(2 * 1024 * 1024 + 1)
                    fname = name.split('/')[-1] if '/' in name else name
                    submission_file_contents.append((fname, data[: 2 * 1024 * 1024]))
                except Exception:
                    pass
        if submission.attachment:
            _add_submission_file(submission.attachment.name)
        for file_obj in HomeworkFile.objects.filter(submission=submission, file_type='submission'):
            if file_obj.file:
                _add_submission_file(file_obj.file.name)
        # Проверка через ИИ: задание (текст + файлы), решение (текст + файлы) → комментарий и оценка 1–5
        ai_service = get_ai_service()
        result = ai_service.check_submission(
            homework_title=submission.homework.title,
            homework_description=submission.homework.description or '',
            homework_max_score=5,
            submission_content=submission.content or '',
            submission_files=submission_files,
            homework_files=homework_files,
            homework_file_paths=homework_file_paths,
            submission_file_paths=submission_file_paths,
            homework_file_contents=homework_file_contents,
            submission_file_contents=submission_file_contents,
            student_name=_student_display_name(submission),
        )
        
        if not result.get('success'):
            return Response(
                {'error': result.get('error', 'Ошибка AI проверки')},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Сохраняем результат AI проверки
        submission.ai_score = result.get('score')
        submission.ai_feedback = result.get('feedback')
        submission.ai_checked_at = timezone.now()
        submission.save(update_fields=['ai_score', 'ai_feedback', 'ai_checked_at'])
        
        from .utils import feedback_to_html
        payload = {
            'success': True,
            'ai_score': submission.ai_score,
            'ai_feedback': submission.ai_feedback,
            'ai_feedback_html': feedback_to_html(submission.ai_feedback or ''),
            'ai_checked_at': submission.ai_checked_at,
            'message': 'AI проверка завершена успешно'
        }
        if result.get('usage'):
            payload['usage'] = result['usage']
        if result.get('skipped_reason'):
            payload['skipped_reason'] = result['skipped_reason']
        return Response(payload)
    
    @action(detail=True, methods=['post'])
    def grade(self, request, pk=None):
        """
        Выставить оценку.
        
        POST /api/homework/submissions/{id}/grade/
        Body: {
            "score": 85,
            "feedback": "Отличная работа!"
        }
        """
        submission = self.get_object()
        
        # Проверяем права
        if submission.homework.mentor != request.user:
            return Response(
                {'error': 'Только ментор может выставить оценку'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = HomeworkGradeSerializer(submission, data=request.data, partial=True, context={'request': request})
        serializer.is_valid(raise_exception=True)
        submission = serializer.save()
        
        # Инвалидируем кеш дашборда после оценки ДЗ
        from apps.users.cache_utils import invalidate_dashboard_cache
        invalidate_dashboard_cache(submission.student.id, 'client')
        invalidate_dashboard_cache(submission.homework.mentor.id, 'mentor')
        
        # Отправляем уведомление студенту
        from apps.notifications.services import NotificationService
        
        feedback_text = ""
        if submission.feedback:
            # Экранируем HTML теги в комментарии, чтобы не сломать разметку Telegram
            escaped_feedback = html.escape(submission.feedback)
            feedback_text = f"\n\n💬 <b>Комментарий:</b>\n{escaped_feedback}"
        
        NotificationService.create_notification_with_telegram(
            recipient=submission.student,
            notification_type='homework_reviewed',
            title='✅ ДЗ проверено',
            message=f'Проверено ДЗ "{submission.homework.title}". Оценка: {submission.score}/5{feedback_text}',
            priority='normal',
            action_url=f'/homework/{submission.homework.id}/submissions/{submission.id}/',
            content_object=submission
        )
        
        response_serializer = HomeworkSubmissionSerializer(submission)
        return Response(response_serializer.data)
    
    @action(detail=False, methods=['get'])
    def by_subject(self, request):
        """
        Получить ДЗ с оценками по выбранному предмету для графика прогресса.
        
        GET /api/homework/submissions/by_subject/
        Query params:
            - subject: название предмета (обязательно)
            - start_date: начальная дата (YYYY-MM-DD, опционально)
            - end_date: конечная дата (YYYY-MM-DD, опционально)
            - child_id: ID ребенка (для родителей, опционально)
        
        Returns: список ДЗ с оценками, отсортированный по дате проверки
        """
        from django.utils.dateparse import parse_date
        from django.db.models import Q
        from apps.schedule.models import Lesson
        
        user = request.user
        subject = request.query_params.get('subject')
        start_date = request.query_params.get('start_date')
        end_date = request.query_params.get('end_date')
        child_id = request.query_params.get('child_id')
        
        if not subject:
            return Response(
                {'error': 'Параметр subject обязателен'},
                status=status.HTTP_400_BAD_REQUEST
            )
        
        # Определяем для какого студента получаем ДЗ
        student_user = user
        if user.role == 'parent' and child_id:
            try:
                from apps.users.models import Client, Parent
                # Получаем профиль родителя
                parent_profile = Parent.objects.get(user=user)
                # child_id - это user_id ребенка, находим Client через User
                child_client = Client.objects.get(user_id=child_id)
                # Проверяем, что ребенок принадлежит этому родителю
                if child_client not in parent_profile.children.all():
                    return Response(
                        {'error': 'Ребенок не найден'},
                        status=status.HTTP_404_NOT_FOUND
                    )
                student_user = child_client.user
            except (Client.DoesNotExist, Parent.DoesNotExist):
                return Response(
                    {'error': 'Ребенок не найден'},
                    status=status.HTTP_404_NOT_FOUND
                )
        elif user.role == 'mentor' and child_id:
            try:
                from apps.users.models import Client
                # child_id — user_id студента; ментор получает ДЗ своего ученика
                student_user = User.objects.get(id=child_id)
                child_client = Client.objects.get(user=student_user)
                # Проверяем, что у ментора есть занятия с этим студентом
                from apps.schedule.models import Lesson
                if not Lesson.objects.filter(mentor=user, client=child_client).exists():
                    return Response(
                        {'error': 'Студент не найден'},
                        status=status.HTTP_404_NOT_FOUND
                    )
            except (User.DoesNotExist, Client.DoesNotExist):
                return Response(
                    {'error': 'Студент не найден'},
                    status=status.HTTP_404_NOT_FOUND
                )
        elif user.role != 'client':
            return Response(
                {'error': 'Доступ запрещен'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # Базовый queryset: только проверенные ДЗ с оценками для студента
        queryset = HomeworkSubmission.objects.filter(
            student=student_user,
            status='graded',
            score__isnull=False,
            checked_at__isnull=False
        ).select_related(
            'homework',
            'homework__lesson',
            'homework__lesson__subject',
            'homework__lesson__mentor_subject',
            'homework__mentor',
            'student'
        )
        
        # Фильтр по предмету через урок
        # Проверяем и subject (ForeignKey) и subject_name (legacy поле)
        # Также проверяем, что урок существует (homework__lesson__isnull=False)
        # Используем OR для всех возможных вариантов названия предмета
        subject_filter = (
            Q(homework__lesson__isnull=False) & (
                Q(homework__lesson__subject__name__iexact=subject) |
                Q(homework__lesson__subject_name__iexact=subject) |
                Q(homework__lesson__mentor_subject__name__iexact=subject)
            )
        )
        
        # Также проверяем, если в сериализаторе homework есть поле lesson_subject
        # Но это поле вычисляемое, поэтому фильтруем только через урок
        
        # Логирование для отладки
        import logging
        logger = logging.getLogger(__name__)
        
        # Сначала получаем все ДЗ без фильтра по предмету для отладки
        debug_queryset = queryset.all()
        logger.info(f'[by_subject] Всего ДЗ для студента {student_user.id}: {debug_queryset.count()}')
        
        # Проверяем, есть ли ДЗ с уроками
        with_lessons = debug_queryset.filter(homework__lesson__isnull=False)
        logger.info(f'[by_subject] ДЗ с уроками: {with_lessons.count()}')
        
        # Проверяем предметы в уроках
        if with_lessons.exists():
            sample = with_lessons.first()
            if sample.homework.lesson:
                lesson = sample.homework.lesson
                logger.info(f'[by_subject] Пример урока: id={lesson.id}, subject={lesson.subject}, subject_name={lesson.subject_name}, mentor_subject={lesson.mentor_subject}')
                if lesson.subject:
                    logger.info(f'[by_subject] subject.name={lesson.subject.name}')
                if lesson.mentor_subject:
                    logger.info(f'[by_subject] mentor_subject.name={lesson.mentor_subject.name}')
        
        queryset = queryset.filter(subject_filter)
        
        logger.info(f'[by_subject] После фильтра по предмету "{subject}": {queryset.count()}')
        
        # Фильтр по дате проверки
        if start_date:
            try:
                start = parse_date(start_date)
                if start:
                    queryset = queryset.filter(checked_at__date__gte=start)
            except (ValueError, TypeError):
                pass
        
        if end_date:
            try:
                end = parse_date(end_date)
                if end:
                    queryset = queryset.filter(checked_at__date__lte=end)
            except (ValueError, TypeError):
                pass
        
        # Сортируем по дате проверки
        queryset = queryset.order_by('checked_at')
        
        # Сериализуем только необходимые поля для графика
        serializer = HomeworkSubmissionSerializer(queryset, many=True)
        
        return Response({
            'count': queryset.count(),
            'results': serializer.data
        })
    
    @action(detail=True, methods=['post'])
    def return_for_revision(self, request, pk=None):
        """
        Вернуть на доработку.
        
        POST /api/homework/submissions/{id}/return_for_revision/
        Body: {
            "feedback": "Необходимо доработать..."
        }
        """
        submission = self.get_object()
        
        # Проверяем права (только ментор задания)
        if submission.homework.mentor != request.user:
            return Response(
                {'error': 'Только ментор может вернуть на доработку'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        serializer = self.get_serializer(submission, data=request.data)
        serializer.is_valid(raise_exception=True)
        submission = serializer.save()
        
        # Отправляем уведомление студенту
        from apps.notifications.services import NotificationService
        msg = f'ДЗ "{submission.homework.title}" возвращено на доработку. Нужно отправить решение заново.'
        if submission.feedback and str(submission.feedback).strip():
            comment = (submission.feedback[:500] + '…') if len(submission.feedback) > 500 else submission.feedback
            msg += f'\n\n💬 Комментарий:\n{comment}'
        NotificationService.create_notification_with_telegram(
            recipient=submission.student,
            notification_type='homework_returned',
            title='🔄 ДЗ возвращено на доработку',
            message=msg,
            priority='normal',
            action_url=f'/homework/{submission.homework.id}/submissions/{submission.id}/',
            content_object=submission
        )
        
        response_serializer = HomeworkSubmissionSerializer(submission)
        return Response(response_serializer.data)
    
    @action(detail=False, methods=['get'])
    def my_submissions(self, request):
        """
        Мои решения (для студентов).
        
        GET /api/homework/submissions/my_submissions/
        """
        submissions = HomeworkSubmission.objects.filter(
            student=request.user
        ).select_related(
            'homework', 'homework__mentor', 'homework__lesson', 
            'homework__lesson__subject', 'homework__lesson__mentor_subject',
            'student', 'checked_by'
        ).only(
            'id', 'homework_id', 'student_id', 'checked_by_id', 'content',
            'score', 'feedback', 'status', 'submitted_at', 'checked_at',
            'is_late', 'passed', 'updated_at'
        )
        
        serializer = HomeworkSubmissionSerializer(submissions, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'])
    def pending(self, request):
        """
        Решения ожидающие проверки (для менторов).
        
        GET /api/homework/submissions/pending/
        """
        submissions = HomeworkSubmission.objects.filter(
            homework__mentor=request.user,
            status='pending'
        ).select_related('homework', 'homework__mentor', 'student', 'checked_by').only(
            'id', 'homework_id', 'student_id', 'checked_by_id', 'content',
            'score', 'feedback', 'status', 'submitted_at', 'checked_at',
            'is_late', 'passed', 'updated_at'
        )
        
        serializer = HomeworkSubmissionSerializer(submissions, many=True)
        return Response(serializer.data)


class HomeworkFileViewSet(viewsets.ModelViewSet):
    """
    ViewSet для управления файлами ДЗ.
    """
    
    permission_classes = [IsAuthenticated]
    serializer_class = HomeworkFileSerializer
    
    def get_queryset(self):
        """Получение файлов."""
        user = self.request.user
        
        queryset = HomeworkFile.objects.filter(
            models.Q(homework__mentor=user) |
            models.Q(submission__student=user) |
            models.Q(uploaded_by=user)
        ).select_related('homework', 'homework__mentor', 'submission', 'submission__student', 'uploaded_by')
        
        # Оптимизация: для списка используем only() для ограничения полей
        if self.action == 'list':
            queryset = queryset.only(
                'id', 'homework_id', 'submission_id', 'file_type', 'file',
                'filename', 'file_size', 'uploaded_by_id', 'created_at'
            )
        
        return queryset.order_by('-created_at')
    
    def perform_create(self, serializer):
        """Создание файла."""
        serializer.save(uploaded_by=self.request.user)


class HomeworkAIAgentViewSet(viewsets.ReadOnlyModelViewSet):
    """
    Список ИИ-агентов для проверки ДЗ (только чтение).
    GET /api/homework/ai-agents/ — какие у нас есть ИИ-агенты.
    """
    permission_classes = [IsAuthenticated]
    serializer_class = HomeworkAIAgentSerializer
    queryset = HomeworkAIAgent.objects.filter(is_active=True).order_by('order', 'name')
