from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from core.models import Course, Testimonial, User, UserInformation, Instructor, UserCourse, InstructorEducation
from .serializers import TestimonialSerializer, TestimonialSerializerMini
from collections import defaultdict
from rest_framework.permissions import IsAuthenticated
from courses.serializers import CourseInstructorSerializer
from django.db.models import Max



class BestInstructor(APIView):
    permission_classes = []

    def get(self, request):
        # Get all testimonials
        testimonials = Testimonial.objects.all()

        # Initialize data structures
        instructor_data = defaultdict(lambda: {
            "instructor_id": None,
            "instructor_name": "",
            "instructor_image": None,
            "total_rating": 0,
            "rating_count": 0,
            "testimonial": []
        })

        # Add all testimonials to the data structure
        for testimonial in testimonials:
            instructor_id = testimonial.instructor_id
            instructor = testimonial.instructor
            instructor_data[instructor_id].update({
                "instructor_id": instructor_id,
                "instructor_name": instructor.user.first_name + " " + instructor.user.last_name,
                "instructor_image": instructor.user.userinformation.image.url if instructor.user.userinformation.image else None,
            })
            instructor_data[instructor_id]["total_rating"] += testimonial.rating
            instructor_data[instructor_id]["rating_count"] += 1
            instructor_data[instructor_id]["testimonial"].append(testimonial.testimonial)  # Add testimonial text

        # Get the latest education for each instructor
        latest_education = InstructorEducation.objects.values('instructor_id').annotate(latest_end=Max('session_end'))

        for education in latest_education:
            instructor_id = education['instructor_id']
            latest_record = InstructorEducation.objects.filter(instructor_id=instructor_id, session_end=education['latest_end']).first()
            if latest_record and instructor_id in instructor_data:
                instructor_data[instructor_id].update({
                    "latest_education": latest_record.degree if latest_record.degree else "",
                    "university_city": latest_record.university_city if latest_record.university_city else "",
                    "university_country": latest_record.university_country if latest_record.university_country else ""
                })

        # Prepare the instructors list
        instructors_list = []
        for data in instructor_data.values():
            if data["rating_count"] > 0:
                avg_rating = data["total_rating"] / data["rating_count"]
            else:
                avg_rating = 0

            instructors_list.append({
                "instructor_name": data["instructor_name"],
                "instructor_image": data["instructor_image"],
                "average_rating": avg_rating,
                "latest_education": data["latest_education"],
                "university_city": data["university_city"],
                "university_country": data["university_country"],
                "testimonial": data["testimonial"]
            })

        # Sort instructors by average rating (highest first)
        best_instructor = sorted(instructors_list, key=lambda x: x["average_rating"], reverse=True)

        # If there's at least one instructor, get the top-rated one
        if best_instructor:
            top_instructor = best_instructor[0]
            response_data = {
                "best_instructor": top_instructor,
            }
            return Response(response_data, status=status.HTTP_200_OK)

        return Response({"error": "No instructors found."}, status=status.HTTP_404_NOT_FOUND)


class TestimonialList(APIView):
    permission_classes = []

    def __init__(self, course_id=None, **kwargs):
        super().__init__(**kwargs)
        self.course_id = course_id


    
    def get(self, request):
        course_id = self.course_id or request.GET.get('course_id', None)
        if course_id is None:
            return Response({"error": "Course ID is required"}, status=400)

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({"detail": "No courses found."},status=status.HTTP_404_NOT_FOUND)

        instructors = course.instructor.all()  # Instructor List Based on course
        testimonials = Testimonial.objects.filter(course_id=course_id)

        # Initialize data structures
        instructor_data = defaultdict(lambda: {
            "instructor_id": None,
            "instructor_name": "",
            "instructors_details": "",
            "total_rating": 0,
            "rating_count": 0,
        })
        
        # Add all instructors to the data structure
        for instructor in instructors:
            instructor_data[instructor.id].update({
                "instructor_id": instructor.id,
                "instructor_name": instructor.name,
                "instructors_details": instructor.details,
                "image": instructor.user.userinformation.image.url if instructor.user.userinformation.image else None,
            })

        # Add testimonial data
        for testimonial in testimonials:
            instructor_id = testimonial.instructor_id
            instructor_data[instructor_id]["total_rating"] += testimonial.rating
            instructor_data[instructor_id]["rating_count"] += 1
        
        # Prepare the instructors list
        instructors_list = []
        for data in instructor_data.values():
            rating_count = data["rating_count"]
            average_rating = data["total_rating"] / rating_count if rating_count > 0 else 0
            instructors_list.append({
                "instructor_id": data["instructor_id"],
                "instructor_name": data["instructor_name"],
                "image": data["image"],
                "instructors_details": data["instructors_details"],
                "average_rating": average_rating,
                "total_rating_count": rating_count,
            })

        # Prepare the testimonials list
        testimonials_data = [
            {
                "testimonial": t.testimonial,
                "user": f"{t.user.first_name} {t.user.last_name}",
                "course": t.course.title,
            } for t in testimonials
        ]

        # Combine data
        response_data = {
            "instructors": instructors_list,
            "testimonials": testimonials_data,
        }

        return Response(response_data, status=status.HTTP_200_OK)

    def post(self, request):
        course_id = request.data['course_id']
        instructor_id = request.data['instructor_id']
        testimonial = request.data['testimonial']
        rating = request.data['rating']

        if not request.user.is_anonymous: 
            if request.user.userinformation.role in ['Student'] :
                existing_testimonial = Testimonial.objects.filter(
                    user=request.user,
                    course_id=course_id,
                    instructor_id=instructor_id
                ).first()

                if existing_testimonial:
                    return Response({"detail": "You have already submitted a testimonial for this course and instructor."},
                                    status=status.HTTP_400_BAD_REQUEST)

                testimonial = Testimonial.objects.create(
                    user=User.objects.get(id=request.user.id),
                    course=Course.objects.get(id=course_id),
                    instructor=Instructor.objects.get(id=instructor_id),
                    testimonial=testimonial,
                    rating=rating
                )

                serializer = TestimonialSerializer(testimonial)

                return Response({"detail": "Testimonial Created"}, status=status.HTTP_201_CREATED)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
                return Response({"detail":"Please login"},status=status.HTTP_401_UNAUTHORIZED)


class TestimonialDetails(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        user = request.user
        
        try:
            user_information = UserInformation.objects.get(user=user)
        except UserInformation.DoesNotExist:
            return Response({'error': 'User information not found.'}, status=status.HTTP_400_BAD_REQUEST)

        if user_information.role != 'Admin':
            return Response({'error': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        testimonial_id = request.data.get('testimonial_id', '')
        testimonial_text = request.data.get('testimonial_text', '')
        rating = request.data.get('rating', '')
        
        try:
            rating = int(rating)
            testimonial_id = int(testimonial_id)
        except:
            return Response({'error': 'Id and rating value must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        if testimonial_id == '':
            return Response({'error': 'Testimonial id not found.'}, status=status.HTTP_404_NOT_FOUND)
        if testimonial_text == '':
            return Response({'error': 'Testimonial text not found.'}, status=status.HTTP_404_NOT_FOUND) 
        if rating == '':
            return Response({'error': 'Rating not found.'}, status=status.HTTP_404_NOT_FOUND)
        if rating < 1 or rating > 5:
            return Response({'error': 'Invalid rating value.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            testimonial = Testimonial.objects.get(id=testimonial_id)
        except Testmonial.DoesNotExist:
            return Response({'error': 'Testimonial not found.'}, status=status.HTTP_404_NOT_FOUND)

        testimonial.testimonial = testimonial_text
        testimonial.rating = rating
        testimonial.save()

        return Response({'success': 'Testimonial updated.'}, status=status.HTTP_200_OK)


    def delete(self, request):
        user = request.user
        
        try:
            user_information = UserInformation.objects.get(user=user)
        except UserInformation.DoesNotExist:
            return Response({'error': 'User information not found.'}, status=status.HTTP_404_NOT_FOUND)

        testimonial_id = request.data.get('testimonial_id', '')

        if testimonial_id == '':
            return Response({'error': 'Testimonial id not found.'}, status=status.HTTP_404_NOT_FOUND)

        try:
            testimonial_id = int(testimonial_id)
        except:
            return Response({'error': 'Testimonial id must be a positive number.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            testimonial = Testimonial.objects.get(id=testimonial_id)
        except Testimonial.DoesNotExist:
            return Response({'error': 'Testimonial not found.'}, status=status.HTTP_404_NOT_FOUND)

        testimonial.delete()

        return Response({'success': 'Testimonial deleted.'}, status=status.HTTP_200_OK)




class TestimonialInstructor(APIView):
    permission_classes = [IsAuthenticated]

    # def __init__(self, course_id=None, instructor_id=None, **kwargs):
    #     super().__init__(**kwargs)
    #     self.course_id = course_id
    #     self.instructor_id = instructor_id
        
    
    def get(self, request):
        course_id = request.GET.get('course_id', None)
        
        if request.user.userinformation.role in ['AdminInstructor', 'Student']:
            instructor_id = request.GET.get('instructor_id', None)
        else:
            instructor_id = Instructor.objects.get(user=request.user)
        if request.user.userinformation.role in ['AdminInstructor', 'Instructor', 'Student']:

            if course_id is None:
                return Response({"error": "Course ID is required"}, status=400)
            if instructor_id is None:
                return Response({"error": "Instructor ID is required"}, status=400)

            if Course.objects.filter(id=course_id).exists():
                testimonials = Testimonial.objects.filter(course_id=course_id, instructor_id=instructor_id)
                
                instructor_testimonials = []
                # Group testimonials by instructor
                for testimonial in testimonials:
                        instructor_data = {
                            "instructor_name": testimonial.instructor.name,
                            "user": f"{testimonial.user.first_name} {testimonial.user.last_name}",
                            "image": testimonial.user.userinformation.image.url if testimonial.user.userinformation.image else None,
                            "testimonial": testimonial.testimonial,
                            "rating": testimonial.rating
                        }
                        instructor_testimonials.append(instructor_data)
                
                if instructor_testimonials:
                    return Response(instructor_testimonials, status=status.HTTP_200_OK)
                else:
                    return Response({"detail": "No testimonials found for this instructor."}, status=status.HTTP_404_NOT_FOUND)
            else:
                return Response({"detail": "No testimonials found."}, status=status.HTTP_404_NOT_FOUND)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)


class TestimonialStudent(APIView):
    permission_classes = [IsAuthenticated]

    def __init__(self, course_id=None, **kwargs):
        super().__init__(**kwargs)
        self.course_id = course_id


    
    def get(self, request):
        course_id = self.course_id or request.GET.get('course_id', None)
        if course_id is None:
            return Response({"error": "Course ID is required"}, status=400)

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({"detail": "No courses found."},status=status.HTTP_404_NOT_FOUND)

        testimonials = Testimonial.objects.filter(course_id=course_id, user=request.user)


        testimonials_data = [
            {
                "testimonial": t.testimonial,
                "course": t.course.title,
                "rating":t.rating,
            } for t in testimonials
        ]

        # Combine data
        response_data = {
            "testimonials": testimonials_data
        }

        return Response(response_data, status=status.HTTP_200_OK)


class TestimonialListAdmin(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user

        try:
            user_information = UserInformation.objects.get(user=user)
        except UserInformation.DoesNotExist:
            return Response({'error': 'User information not found.'}, status=status.HTTP_400_BAD_REQUEST)

        if user_information.role != 'Admin':
            return Response({'error': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        course_id = request.GET.get('course_id', '')
        instructor_id = request.GET.get('instructor_id', '')

        if course_id == '':
            return Response({'error': 'Course id not found.'}, status=status.HTTP_404_NOT_FOUND)

        if instructor_id == '':
            return Response({'error': 'Instructor id not found.'}, status=status.HTTP_404_NOT_FOUND)    
        
        try:
            course_id = int(course_id)
        except: 
            return Response({'error': 'Course id must be a positive number.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            instructor_id = int(instructor_id)
        except: 
            return Response({'error': 'Instructor id must be a positive number.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            instructor = Instructor.objects.get(id=instructor_id)
        except Instructor.DoesNotExist: 
            return Response({'error': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)

        testimonials = Testimonial.objects.filter(course__id=course_id, instructor__id=instructor_id)

        serializer = TestimonialSerializerMini(testimonials, many=True)
        
        return Response({'testimonial_data': serializer.data, 'instructor_name': instructor.name}, status=status.HTTP_200_OK)

        
