"""
API views для прогресса студентов.
"""
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.models import Q, Count, Value, Case, When, F, CharField
from django.utils import timezone
from datetime import timedelta, datetime

from apps.users.models import User, Client
from apps.schedule.models import Lesson
from apps.homework.models import HomeworkSubmission, Homework
from apps.users.utils import format_datetime_for_user


def _lesson_display_subject(lesson):
    """Название предмета для занятия: subject_name, иначе subject, иначе mentor_subject."""
    if lesson.subject_name and lesson.subject_name.strip():
        return lesson.subject_name.strip()
    if lesson.subject_id and lesson.subject:
        return lesson.subject.name
    if lesson.mentor_subject_id and lesson.mentor_subject:
        return lesson.mentor_subject.name
    return 'Другое'


class StudentProgressViewSet(viewsets.ViewSet):
    """ViewSet для прогресса студентов."""
    
    permission_classes = [IsAuthenticated]
    
    @action(detail=False, methods=['get'], url_path='(?P<student_id>[^/.]+)/progress')
    def student_progress(self, request, student_id=None):
        """
        Получить детальный прогресс студента по предметам.
        
        GET /api/student-progress/{student_id}/progress/
        student_id - это ID клиента (Client.id), не User.id
        """
        try:
            # student_id это Client ID, находим User через Client
            client = Client.objects.select_related('user').get(id=student_id)
            student = client.user
        except Client.DoesNotExist:
            return Response(
                {'error': 'Студент не найден'},
                status=status.HTTP_404_NOT_FOUND
            )
        
        # Проверяем что это студент текущего ментора
        # (пропускаем проверку, так как структура модели может отличаться)

        # Фильтры из query-параметров: subject, start_date, end_date
        subject_filter = request.query_params.get('subject', '').strip()
        start_date_str = request.query_params.get('start_date', '').strip()
        end_date_str = request.query_params.get('end_date', '').strip()
        start_date = None
        end_date = None
        if start_date_str:
            try:
                start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
            except ValueError:
                pass
        if end_date_str:
            try:
                end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
            except ValueError:
                pass

        # База занятий: ментор + студент + период (без фильтра по предмету)
        # Список предметов в ответе всегда полный — для выпадающего списка на фронте.
        lessons_base = Lesson.objects.filter(
            Q(client=client) | Q(group__isnull=False),
            mentor=request.user
        ).select_related('subject', 'mentor_subject').annotate(
            display_subject=Case(
                When(subject_name__gt='', then=F('subject_name')),
                When(subject__isnull=False, then=F('subject__name')),
                When(mentor_subject__isnull=False, then=F('mentor_subject__name')),
                default=Value('Другое'),
                output_field=CharField(),
            )
        )
        if start_date:
            lessons_base = lessons_base.filter(start_time__date__gte=start_date)
        if end_date:
            lessons_base = lessons_base.filter(start_time__date__lte=end_date)

        # Для графика по дням — фильтр по предмету (если передан).
        lessons_filtered = lessons_base
        if subject_filter:
            lessons_filtered = lessons_filtered.filter(display_subject=subject_filter)

        # Делаем порядок предметов стабильным (важно для "первого в селекте" на фронте)
        lessons_by_subject = lessons_base.values('display_subject').annotate(
            total_lessons=Count('id'),
            completed_lessons=Count('id', filter=Q(status='completed')),
        ).order_by('display_subject')

        subjects_stats = {}
        for item in lessons_by_subject:
            name = item['display_subject'] or 'Другое'
            subjects_stats[name] = {
                'subject': name,
                'total_lessons': item['total_lessons'],
                'completed_lessons': item['completed_lessons'],
                'grades': [],
                'average_grade': 0,
                'homework_count': 0,
                'homework_completed': 0,
                'homework_average': 0,
            }

        completed_lessons = lessons_base.filter(status='completed')
        for lesson in completed_lessons:
            grade = None
            if hasattr(lesson, 'mentor_grade') and lesson.mentor_grade:
                grade = float(lesson.mentor_grade)
            elif hasattr(lesson, 'school_grade') and lesson.school_grade:
                grade = float(lesson.school_grade)
            if not grade:
                continue
            name = lesson.display_subject or 'Другое'
            if name not in subjects_stats:
                subjects_stats[name] = {
                    'subject': name,
                    'total_lessons': 0,
                    'completed_lessons': 0,
                    'grades': [],
                    'average_grade': 0,
                    'homework_count': 0,
                    'homework_completed': 0,
                    'homework_average': 0,
                }
            subjects_stats[name]['grades'].append({
                'grade': grade,
                'date': format_datetime_for_user(lesson.start_time, request.user.timezone) if lesson.start_time else '',
                'comment': lesson.title or '',
            })
        
        lesson_ids = list(lessons_base.values_list('id', flat=True))
        submissions_qs = HomeworkSubmission.objects.filter(
            student=student,
            status='graded',
            homework__lesson_id__in=lesson_ids
        ).select_related(
            'homework', 'homework__lesson', 'homework__lesson__subject', 'homework__lesson__mentor_subject'
        ).only(
            'id', 'homework_id', 'student_id', 'score', 'passed', 'submitted_at', 'updated_at'
        )
        submissions = list(submissions_qs)

        for sub in submissions:
            lesson = sub.homework.lesson if sub.homework else None
            if not lesson:
                continue
            name = _lesson_display_subject(lesson)
            if name not in subjects_stats:
                subjects_stats[name] = {
                    'subject': name,
                    'total_lessons': 0,
                    'completed_lessons': 0,
                    'grades': [],
                    'average_grade': 0,
                    'homework_count': 0,
                    'homework_completed': 0,
                    'homework_average': 0,
                }
            subjects_stats[name]['homework_count'] = subjects_stats[name].get('homework_count', 0) + 1
            if sub.passed:
                subjects_stats[name]['homework_completed'] = subjects_stats[name].get('homework_completed', 0) + 1
            if sub.score is not None:
                subjects_stats[name]['grades'].append({
                    'grade': float(sub.score),
                    'date': format_datetime_for_user(sub.submitted_at or sub.updated_at, request.user.timezone) if (sub.submitted_at or sub.updated_at) else None,
                    'comment': f'ДЗ: {sub.homework.title}',
                })
        
        for subject, stats in subjects_stats.items():
            if stats['grades']:
                stats['average_grade'] = sum(g['grade'] for g in stats['grades']) / len(stats['grades'])
                stats['grades'].sort(key=lambda x: x['date'] or '')
            
            if stats['homework_count'] > 0:
                stats['homework_average'] = (stats['homework_completed'] / stats['homework_count']) * 100
        
        all_grades = []
        for stats in subjects_stats.values():
            all_grades.extend(stats['grades'])
        overall_average = sum(g['grade'] for g in all_grades) / len(all_grades) if all_grades else 0

        daily_stats = []
        if start_date and end_date and start_date <= end_date:
            daily_agg = lessons_filtered.values('start_time__date').annotate(
                total_lessons=Count('id'),
                completed_lessons=Count('id', filter=Q(status='completed')),
            )
            by_date = {
                row['start_time__date']: {
                    'total_lessons': row['total_lessons'],
                    'completed_lessons': row['completed_lessons'],
                }
                for row in daily_agg
                if row.get('start_time__date')
            }
            current = start_date
            while current <= end_date:
                e = by_date.get(current, {'total_lessons': 0, 'completed_lessons': 0})
                daily_stats.append({
                    'date': current.isoformat(),
                    'total_lessons': e['total_lessons'],
                    'completed_lessons': e['completed_lessons'],
                })
                current += timedelta(days=1)

        if start_date and end_date:
            recent_submissions = [
                s for s in submissions
                if s.submitted_at and start_date <= s.submitted_at.date() <= end_date
            ]
            recent_submissions.sort(key=lambda s: s.submitted_at or s.updated_at)
        else:
            thirty_days_ago = timezone.now() - timedelta(days=30)
            recent_submissions = [
                s for s in submissions
                if (s.submitted_at or s.updated_at) and (s.submitted_at or s.updated_at) >= thirty_days_ago
            ]
            recent_submissions.sort(key=lambda s: s.submitted_at or s.updated_at)

        progress_timeline = []
        for sub in recent_submissions:
            if sub.score is None:
                continue
            lesson = sub.homework.lesson if sub.homework else None
            subject_name = _lesson_display_subject(lesson) if lesson else 'Другое'
            progress_timeline.append({
                'date': format_datetime_for_user(sub.submitted_at or sub.updated_at, request.user.timezone) if (sub.submitted_at or sub.updated_at) else None,
                'grade': float(sub.score),
                'subject': subject_name,
                'comment': f'ДЗ: {sub.homework.title}',
            })
        
        return Response({
            'student': {
                'id': student.id,
                'name': f'{student.first_name} {student.last_name}',
                'email': student.email,
            },
            'overall': {
                'average_grade': round(overall_average, 2),
                'total_lessons': sum(s['total_lessons'] for s in subjects_stats.values()),
                'completed_lessons': sum(s['completed_lessons'] for s in subjects_stats.values()),
                'total_grades': len(all_grades),
            },
            'subjects': list(subjects_stats.values()),
            'progress_timeline': progress_timeline,
            'daily_stats': daily_stats,
        })

