from rest_framework import generics, status
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.db import transaction
import random
from course.models import Question, Exam, ExamAnswer, ExamResult, Certificate, CourseEnrollment, AllCourse
from course.serializers_exam import (
    QuestionSerializer, QuestionStudentSerializer, ExamSerializer, 
    ExamResultSerializer, CertificateSearchSerializer
)
from users.models import UserRole

# Question Management (Trainers only)
class QuestionListCreateView(generics.ListCreateAPIView):
    serializer_class = QuestionSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        if self.request.user.role != UserRole.TRAINER.value:
            return Question.objects.none()
        return Question.objects.filter(course_id=self.kwargs['course_id'])
    
    def perform_create(self, serializer):
        if self.request.user.role != UserRole.TRAINER.value:
            return Response({'error': 'Only trainers can add questions'}, status=403)
        serializer.save(course_id=self.kwargs['course_id'])

class QuestionDetailView(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = QuestionSerializer
    permission_classes = [IsAuthenticated]
    
    def get_queryset(self):
        if self.request.user.role != UserRole.TRAINER.value:
            return Question.objects.none()
        return Question.objects.all()

# Exam functionality
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def start_exam(request, course_id):
    """Start exam for a student"""
    try:
        enrollment = CourseEnrollment.objects.get(
            course_id=course_id,
            student__profile__user=request.user
        )
        
        if not enrollment.can_take_exam():
            return Response({'error': 'Course not completed or exam already active'}, status=400)
        
        # Check if questions exist
        questions = Question.objects.filter(course_id=course_id)
        if questions.count() < 250:
            return Response({'error': 'Insufficient questions for exam'}, status=400)
        
        # Create exam
        exam = Exam.objects.create(enrollment=enrollment)
        
        # Get random 250 questions
        exam_questions = random.sample(list(questions), 250)
        serializer = QuestionStudentSerializer(exam_questions, many=True)
        
        return Response({
            'exam_id': exam.id,
            'expires_at': exam.expires_at,
            'questions': serializer.data
        })
        
    except CourseEnrollment.DoesNotExist:
        return Response({'error': 'Enrollment not found'}, status=404)

@api_view(['POST'])
@permission_classes([IsAuthenticated])
def submit_exam(request, exam_id):
    """Submit exam answers"""
    try:
        exam = get_object_or_404(Exam, id=exam_id, enrollment__student__profile__user=request.user)
        
        if exam.submitted_at:
            return Response({'error': 'Exam already submitted'}, status=400)
        
        if exam.is_expired:
            return Response({'error': 'Exam time expired'}, status=400)
        
        answers_data = request.data.get('answers', [])
        
        with transaction.atomic():
            # Save answers
            for answer_data in answers_data:
                ExamAnswer.objects.create(
                    exam=exam,
                    question_id=answer_data['question'],
                    selected_answer=answer_data['selected_answer']
                )
            
            # Calculate score
            correct_count = 0
            total_questions = 250
            
            for answer in exam.answers.all():
                if answer.selected_answer == answer.question.correct_answer:
                    correct_count += 1
            
            score_percentage = (correct_count / total_questions) * 100
            exam.score = score_percentage
            exam.is_passed = score_percentage >= 85.0
            exam.submitted_at = timezone.now()
            exam.save()
            
            # Create exam result
            ExamResult.objects.create(
                exam=exam,
                total_questions=total_questions,
                correct_answers=correct_count,
                score_percentage=score_percentage
            )
            
            # Generate certificate if passed
            if exam.is_passed:
                Certificate.objects.create(
                    course=exam.enrollment.course,
                    student=exam.enrollment.student,
                    exam_score=score_percentage
                )
        
        return Response({
            'score': score_percentage,
            'passed': exam.is_passed,
            'certificate_generated': exam.is_passed
        })
        
    except Exception as e:
        return Response({'error': str(e)}, status=500)

# Leaderboard
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def leaderboard(request, course_id=None):
    """Get exam leaderboard"""
    if request.user.role not in [UserRole.TRAINER.value, UserRole.ADMIN.value]:
        return Response({'error': 'Permission denied'}, status=403)
    
    queryset = ExamResult.objects.all()
    if course_id:
        queryset = queryset.filter(exam__enrollment__course_id=course_id)
    
    serializer = ExamResultSerializer(queryset[:100], many=True)  # Top 100
    return Response(serializer.data)

# Certificate search with binary search
def binary_search_certificate(certificates, target_number):
    """Binary search for certificate by number"""
    left, right = 0, len(certificates) - 1
    
    while left <= right:
        mid = (left + right) // 2
        if certificates[mid].certificate_number == target_number:
            return certificates[mid]
        elif certificates[mid].certificate_number < target_number:
            left = mid + 1
        else:
            right = mid - 1
    
    return None

@api_view(['GET'])
def search_certificate(request):
    """Search certificate by number, student_id, or course_id"""
    cert_number = request.GET.get('certificate_number')
    student_id = request.GET.get('student_id')
    course_id = request.GET.get('course_id')
    
    if cert_number:
        # Use binary search for certificate number
        certificates = list(Certificate.objects.all().order_by('certificate_number'))
        certificate = binary_search_certificate(certificates, cert_number)
        if certificate:
            serializer = CertificateSearchSerializer(certificate)
            return Response(serializer.data)
    
    # Regular filtering for other parameters
    queryset = Certificate.objects.all()
    if student_id:
        queryset = queryset.filter(student_id=student_id)
    if course_id:
        queryset = queryset.filter(course_id=course_id)
    
    serializer = CertificateSearchSerializer(queryset, many=True)
    return Response(serializer.data)

from django.http import HttpResponse, Http404

@api_view(['GET'])
def download_certificate(request, certificate_id):
    """Download certificate PDF"""
    try:
        certificate = Certificate.objects.get(id=certificate_id)
        from course.certificate_generator import generate_certificate_pdf
        return generate_certificate_pdf(certificate)
        
    except Certificate.DoesNotExist:
        raise Http404("Certificate not found")
    except Exception as e:
        return HttpResponse(f'Error: {str(e)}', status=500)