from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.db.models import Avg, Count, Sum, Max, Q

from .models import Country, Category, QuestionAnswer, UserQuizPerformance, Feedback
from .serializers import (
    QuestionAnswerSerializer,
    CategorySerializer,
    UserQuizPerformanceSerializer,
    FeedbackSerializer,
)
from django.shortcuts import get_object_or_404
from django.utils import timezone
from users.models import CustomUser


class CategoryByCountryAPIView(APIView):
    def get(self, request):
        country_id = request.query_params.get('country')
        if not country_id:
            return Response({'error': 'country is required'}, status=status.HTTP_400_BAD_REQUEST)
        from .models import Country, Category
        country = get_object_or_404(Country, id=country_id)
        categories = Category.objects.filter(country=country)
        serializer = CategorySerializer(categories, many=True)
        return Response({'categories': serializer.data}, status=status.HTTP_200_OK) 


class GetQuestionsAPIView(APIView):
    def get(self, request):
        import random
        country_id = request.query_params.get('country')
        category_id = request.query_params.get('category')
        language = request.query_params.get('language')
        if not country_id or not category_id or not language:
            return Response({'error': 'country, category and language are required'}, status=status.HTTP_400_BAD_REQUEST)
        country = get_object_or_404(Country, id=country_id)
        category = get_object_or_404(Category, id=category_id, country=country)
        # Get questions by difficulty
        easy_qs = list(QuestionAnswer.objects.filter(country=country, category=category, difficulty__iexact='easy', language=language))
        medium_qs = list(QuestionAnswer.objects.filter(country=country, category=category, difficulty__iexact='medium', language=language))
        hard_qs = list(QuestionAnswer.objects.filter(country=country, category=category, difficulty__iexact='hard', language=language))
        # Shuffle within each group
        random.shuffle(easy_qs)
        random.shuffle(medium_qs)
        random.shuffle(hard_qs)
        # Select up to 5 from each
        easy_sample = easy_qs[:5]
        medium_sample = medium_qs[:5]
        hard_sample = hard_qs[:5]
        questions = easy_sample + medium_sample + hard_sample
        if not questions:
            return Response({'message': 'No questions found', 'questions': []}, status=status.HTTP_200_OK)
        serializer = QuestionAnswerSerializer(questions, many=True)
        return Response({'message': 'Questions fetched successfully', 'questions': serializer.data}, status=status.HTTP_200_OK)


class UserQuizPerformanceAPIView(APIView):
    def post(self, request):
        """Save or update user quiz performance"""
        try:
            # Find user by email from user_id field
            user_email = request.data.get('user_id')
            if not user_email:
                return Response({'error': 'user_id is required'}, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                user = CustomUser.objects.get(email=user_email)
            except CustomUser.DoesNotExist:
                return Response({'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND)
            
            # Calculate average score as percentage
            total_questions = request.data.get('total_questions', 0)
            correct_answers = request.data.get('correct_answers', 0)
            calculated_score = 0.0
            if total_questions > 0:
                calculated_score = (correct_answers / total_questions) * 100
            
            # Validate and correct time_taken_seconds to ensure it's positive
            time_taken_seconds = request.data.get('time_taken_seconds', 0)
            if time_taken_seconds < 0:
                time_taken_seconds = abs(time_taken_seconds)  # Make it positive
                print(f"Warning: Negative time_taken_seconds received: {request.data.get('time_taken_seconds')}, corrected to: {time_taken_seconds}")
            
            # Get or create performance record
            performance, created = UserQuizPerformance.objects.get_or_create(
                user=user,
                country_id=request.data.get('country_id'),
                category_id=request.data.get('category_id'),
                defaults={
                    'country_name': request.data.get('country_name'),
                    'category_name': request.data.get('category_name'),
                    'reason': request.data.get('reason', 'quit'),
                    'questions_answered': request.data.get('questions_answered', 0),
                    'total_questions': total_questions,
                    'correct_answers': correct_answers,
                    'average_score': calculated_score,
                    'time_taken_seconds': time_taken_seconds,
                    'current_question_time': request.data.get('current_question_time', 0),
                    'current_question_index': request.data.get('current_question_index', 0),
                    'used_lifelines': request.data.get('used_lifelines', []),
                    'trophies': 1 if request.data.get('reason') == 'completed' else 0,
                }
            )
            
            if not created:
                # Update existing record
                performance.country_name = request.data.get('country_name')
                performance.category_name = request.data.get('category_name')
                performance.reason = request.data.get('reason', 'quit')
                performance.questions_answered = request.data.get('questions_answered', 0)
                performance.total_questions = total_questions
                performance.correct_answers = correct_answers
                performance.average_score = calculated_score
                performance.time_taken_seconds = time_taken_seconds
                performance.current_question_time = request.data.get('current_question_time', 0)
                performance.current_question_index = request.data.get('current_question_index', 0)
                performance.used_lifelines = request.data.get('used_lifelines', [])
                performance.quiz_attempted_at = timezone.now()
                # Increment trophies if reason is 'completed'
                if request.data.get('reason') == 'completed':
                    performance.trophies += 1
                performance.update_best_performance()
            
            serializer = UserQuizPerformanceSerializer(performance)
            return Response({
                'message': 'Performance saved successfully',
                'performance': serializer.data,
                'calculated_score': calculated_score,
                'trophies': performance.trophies
            }, status=status.HTTP_200_OK)
            
        except Exception as e:
            print(e)
            return Response({
                'error': f'Failed to save performance: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)

    def get(self, request):
        """Get user's recent quiz performances and overall statistics"""
        try:
            # For GET request, you might want to pass user_id as query param
            user_email = request.query_params.get('user_id')
            if not user_email:
                return Response({'error': 'user_id is required'}, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                user = CustomUser.objects.get(email=user_email)
            except CustomUser.DoesNotExist:
                return Response({'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND)
            
            # Get recent 5 quiz attempts
            recent_performances = UserQuizPerformance.objects.filter(user=user).order_by('-quiz_attempted_at')[:5]
            recent_serializer = UserQuizPerformanceSerializer(recent_performances, many=True)
            
            # Calculate overall statistics
            all_performances = UserQuizPerformance.objects.filter(user=user)
            
            # Overall statistics
            total_quizzes_attempted = all_performances.count()
            total_questions_attempted = sum(perf.total_attempts for perf in all_performances)
            
            # Calculate overall average score
            total_score = sum(perf.average_score for perf in all_performances)
            overall_average_score = total_score / total_quizzes_attempted if total_quizzes_attempted > 0 else 0.0
            
            # Get best score overall
            best_score_overall = max(perf.best_score for perf in all_performances) if all_performances.exists() else 0.0
            
            # Get total trophies
            total_trophies = sum(perf.trophies for perf in all_performances)
            
            return Response({
                'message': 'Performance data retrieved successfully',
                'recent_quizzes': recent_serializer.data,
                'overall_statistics': {
                    'total_quizzes_attempted': total_quizzes_attempted,
                    'total_questions_attempted': total_questions_attempted,
                    'overall_average_score': round(overall_average_score, 2),
                    'best_score_overall': round(best_score_overall, 2),
                    'trophies': total_trophies
                }
            }, status=status.HTTP_200_OK)
        except Exception as e:
            return Response({
                'error': f'Failed to retrieve performance: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)


class LeaderboardAPIView(APIView):
    def get(self, request):
        """Get leaderboard with user position and top 10 users"""
        try:
            user_email = request.query_params.get('user_id')
            if not user_email:
                return Response({'error': 'user_id is required'}, status=status.HTTP_400_BAD_REQUEST)
            
            try:
                user = CustomUser.objects.get(email=user_email)
            except CustomUser.DoesNotExist:
                return Response({'error': 'User not found'}, status=status.HTTP_404_NOT_FOUND)
            
            # Get all users with their average scores
            # Simplified query to avoid aggregation issues with djongo
            user_stats = UserQuizPerformance.objects.values('user__email', 'user__first_name', 'user__last_name','user__gender').annotate(
                total_quizzes=Count('id'),
                overall_average_score=Avg('average_score')
            ).order_by('-overall_average_score', '-total_quizzes')
            
            # Convert to list for easier manipulation
            user_stats_list = list(user_stats)
            
            # Filter out users with 0 quizzes (since we removed the HAVING clause)
            user_stats_list = [stats for stats in user_stats_list if stats['total_quizzes'] > 0]
            
            # Handle case where no users have attempted quizzes
            if not user_stats_list:
                return Response({
                    'message': 'No users have attempted quizzes yet',
                    'user_position': 1,
                    'total_users': 0,
                    'user_stats': {
                        'email': user.email,
                        'total_quizzes': 0,
                        'total_questions_attempted': 0,
                        'overall_average_score': 0.0,
                        'best_score_overall': 0.0,
                        'trophies': 0,
                        'gender': user.gender
                    },
                    'top_10_users': []
                }, status=status.HTTP_200_OK)
            
            # Calculate total trophies for each user and sort accordingly
            user_stats_list_with_trophies = []
            for stats in user_stats_list:
                user_performances = UserQuizPerformance.objects.filter(user__email=stats['user__email'])
                total_trophies = sum(perf.trophies for perf in user_performances)
                stats['trophies'] = total_trophies
                stats['overall_average_score'] = stats['overall_average_score'] or 0
                user_stats_list_with_trophies.append(stats)
            # Sort by trophies DESC, then average score DESC, then total quizzes DESC
            user_stats_list_with_trophies.sort(key=lambda x: (-x['trophies'], -x['overall_average_score'], -x['total_quizzes']))
            user_stats_list = user_stats_list_with_trophies
            
            # Find user's position
            user_position = None
            user_stats_data = None
            
            for i, stats in enumerate(user_stats_list):
                if stats['user__email'] == user_email:
                    user_position = i + 1  # Position is 1-indexed
                    # Get additional stats for this specific user
                    user_performances = UserQuizPerformance.objects.filter(user__email=stats['user__email'])
                    total_questions_attempted = sum(perf.questions_answered for perf in user_performances)
                    best_score_overall = max(perf.best_score for perf in user_performances) if user_performances.exists() else 0.0
                    total_trophies = stats['trophies']
                    user_stats_data = {
                        'email': stats['user__email'],
                        'gender': stats['user__gender'],
                        'first_name': stats['user__first_name'] or '',
                        'last_name': stats['user__last_name'] or '',
                        'total_quizzes': stats['total_quizzes'],
                        'total_questions_attempted': total_questions_attempted,
                        'overall_average_score': round(stats['overall_average_score'] or 0, 2),
                        'best_score_overall': round(best_score_overall, 2),
                        'trophies': total_trophies
                    }
                    break
            
            # If user not found in leaderboard (no quizzes attempted), set position to last
            if user_position is None:
                user_position = len(user_stats_list) + 1
                user_stats_data = {
                    'email': user.email,
                    'gender': user.gender,
                    'first_name': user.first_name or '',
                    'last_name': user.last_name or '',
                    'total_quizzes': 0,
                    'total_questions_attempted': 0,
                    'overall_average_score': 0.0,
                    'best_score_overall': 0.0,
                    'trophies': 0
                }
            
            # Get top 10 users
            top_10_users = []
            for i, stats in enumerate(user_stats_list[:10]):
                # Get additional stats for each user
                user_performances = UserQuizPerformance.objects.filter(user__email=stats['user__email'])
                total_questions_attempted = sum(perf.questions_answered for perf in user_performances)
                best_score_overall = max(perf.best_score for perf in user_performances) if user_performances.exists() else 0.0
                total_trophies = stats['trophies']
                top_10_users.append({
                    'position': i + 1,
                    'email': stats['user__email'],
                    'gender': stats['user__gender'],
                    'first_name': stats['user__first_name'] or '',
                    'last_name': stats['user__last_name'] or '',
                    'total_quizzes': stats['total_quizzes'],
                    'total_questions_attempted': total_questions_attempted,
                    'overall_average_score': round(stats['overall_average_score'] or 0, 2),
                    'best_score_overall': round(best_score_overall, 2),
                    'trophies': total_trophies
                })
            
            return Response({
                'message': 'Leaderboard data retrieved successfully',
                'user_position': user_position,
                'total_users': len(user_stats_list),
                'user_stats': user_stats_data,
                'top_10_users': top_10_users
            }, status=status.HTTP_200_OK)
            
        except Exception as e:
            print(f"Leaderboard error: {e}")
            import traceback
            traceback.print_exc()
            return Response({
                'error': f'Failed to retrieve leaderboard: {str(e)}'
            }, status=status.HTTP_400_BAD_REQUEST)


class ReportQuestionAPIView(APIView):
    def post(self, request):
        serializer = FeedbackSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({'message': 'Feedback submitted successfully', 'feedback': serializer.data}, status=status.HTTP_201_CREATED)
        return Response({'error': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

    def get(self, request):
        feedbacks = Feedback.objects.all()
        serializer = FeedbackSerializer(feedbacks, many=True)
        return Response({'message': 'Feedbacks fetched successfully', 'feedbacks': serializer.data}, status=status.HTTP_200_OK)