import os, json, datetime, math, pytz, shutil
import dateutil.parser
from subprocess import call
from django.contrib.auth.models import User
from django.db.models.fields.mixins import NOT_PROVIDED
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import Http404
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from django.shortcuts import render
from django.db.models import Q
from rest_framework import status
from core.models import (Course, Instructor, CourseContent, UserInformation, Video, LectureNote,
                         Homework, HomeworkSubmission, HoldWeek, UserCourse, HomeworkSubReview,
                         ExamFeedback, AcademicSession, HomeworkSubComment,
                         HomeworkSubNewComment, InstructorHoldWeek, CoursePayment, Consultation, CourseContentDocument,
                         CourseContentResource)
from . serializers import (CourseSerializer, CourseContentSerializer, CourseContentMinSerializer,
                           CourseContentVideoSerializer, CourseContentDocumentSerializer, CourseContentResourceSerializer, LectureNoteSerializer, HomeworkSerializer,
                           HomeworkSubmissionSerializer, StudentHomeworkSubmissionSerializer,
                           HomeworkSubReviewSerializer, AcademicSessionSerializer,
                           HomeworkSubCommentSerializer, MiniCourseSerializer, SuggestedCourseSerializer,
                           MiniCourseSerializerAdmin, AcademicSessionSerializerMini, UserCourseSerializerAdmin, ConsultationSerializer,
                           CourseSerializerMini)
from core.permissions import IsAdmin, IsOrgAdmin, IsInstructor, IsStudent, IsGuardian
from students.serializers import ExamFeedbackSerializer
from django.core.exceptions import ObjectDoesNotExist

os.environ["IMAGEIO_FFMPEG_EXE"] = "/usr/bin/ffmpeg"
# from moviepy.editor import VideoFileClip
from django.core.mail import send_mail
from django.conf import settings
from courses import serializers
from testimonial.views import TestimonialList


def get_parent_directory(dir):
  relative_parent = os.path.join(dir, "..")
  return os.path.abspath(relative_parent)


def get_file_size(s):
    y = 1048576
    if s < y:
        value = round(s/1024, 2)
        ext = ' kB'
    elif s < y*1024:
        value = round(s/1048576, 2)
        ext = ' MB'
    else:
        value = round(s/1073741824, 2)
        ext = ' GB'

    return str(value)+ext


def get_video_duration(seconds):
    if seconds > 3600:
        hour = math.floor(seconds / 3600)
        min = math.floor((seconds - (hour * 3600)) / 60)
        sec = seconds - hour * 3600 - min * 60

        return f'{hour} hr {min} min'

    if seconds > 60:
        min = math.floor(seconds / 60)
        sec = seconds - min * 60

        return f'{min} min {sec} sec'
    else:
        return f'{seconds} sec'


class CourseList(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsInstructor | IsOrgAdmin]

    def get(self, request):
        course_status = request.GET.get('course_status', '')

        user = request.user
        user_information = user.userinformation

        if user_information.role == 'Admin':
            courses = Course.objects.filter(course_status__icontains=course_status).order_by('-id')
            serializer = CourseSerializer(courses, many=True)
        elif user_information.role == 'Instructor':
            courses = Course.objects.filter(instructor=user.instructor, course_status__icontains=course_status).order_by('-id')
            serializer = CourseSerializer(courses, many=True)
        else:
            courses = Course.objects.filter(organization=user_information.organization, course_status__icontains=course_status).order_by('-id')
            serializer = CourseSerializer(courses, many=True)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course list fetched.'}, status=status.HTTP_200_OK)

    def post(self, request):
        user = request.user
        user_information = user.userinformation

        title = request.data.get('title', None)
        details = request.data.get('details', None)
        country_fees = request.data.get('country_fees', None)
        student_limit = request.data.get('student_limit', None)
        duration = request.data.get('duration', None)
        start_date = request.data.get('start_date', None)
        end_date = request.data.get('end_date', None)    
        group_discount = request.data.get('group_discount', None)
        grade_level = request.data.get('organization', None)
        education_type = request.data.get('education_type', None)
        grade_class = request.data.get('grade_class', None)
        subject = request.data.get('subject', [])
        instructors = request.data.get('instructors', [])
        is_one_to_one = request.data.get('is_one_to_one', '')
        is_one_to_group = request.data.get('is_one_to_group', '')
        is_one_to_many = request.data.get('is_one_to_many', '')
        is_selfpaced = request.data.get('is_selfpaced', '')
        is_organization = request.data.get('is_organization', '')
        organization = request.data.get('organization', None)
        image = request.FILES.get('image', None)
        syllabus = request.FILES.get('syllabus', None)

        study_method = request.data.get('study_method', None)
        assessments = request.data.get('assessments', None)
        entry_requirements = request.data.get('entry_requirements', None)
        language = request.data.get('language', None)
        what_you_will_learn = request.data.get('what_you_will_learn', None)
        topics_covered = request.data.get('topics_covered', None)
        description = request.data.get('description', None)
        assessment_details = request.data.get('assessment_details', None)
        textbooks = request.data.get('textbooks', None)
        regarding_requirements = request.data.get('regarding_requirements', None)
        about_study_loans = request.data.get('about_study_loans', None)
        why_focus_on_one_subject = request.data.get('why_focus_on_one_subject', None)
        what_to_learn_next = request.data.get('what_to_learn_next', None)
        faq = request.data.get('faq', '')
        course_status = request.data.get('course_status', '')

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter course title.'}, status=status.HTTP_400_BAD_REQUEST)

        if not image:
            return Response({'status': False, 'data': None, 'msg': 'Please upload course image.'}, status=status.HTTP_400_BAD_REQUEST)

        if not details:
            return Response({'status': False, 'data': None, 'msg': 'Please enter course details.'}, status=status.HTTP_400_BAD_REQUEST)

        if course_status not in ['Draft', 'Pending', 'Approved']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)
        
        if user_information.role=='Instructor' and course_status=='Approved':
            return Response({'status': False, 'data': None, 'msg': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            duration = int(duration)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Course duration must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        if not grade_level:
            grade_level = None

        if not education_type:
            education_type = None

        if not grade_class:
            grade_class = None

        if subject:
            subject = json.loads(subject)
        else:
            subject = []

        if group_discount:
            try:
                group_discount = json.loads(group_discount)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid group discount JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            group_discount = None

        if country_fees:
            try:
                country_fees = json.loads(country_fees)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid country fees JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            country_fees = None

        if instructors:
            try:
                instructors = json.loads(instructors)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid instructor JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            instructors = None

        if faq:
            try:
                faq = json.loads(faq)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid faq JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            faq = None




        if subject:
            subject = json.loads(subject)
        else:
            subject = []

        if is_one_to_one.lower()=='true':
            is_one_to_one = True
        else:
            is_one_to_one = False

        if is_one_to_group.lower()=='true':
            is_one_to_group = True
        else:
            is_one_to_group = False

        if is_one_to_many.lower()=='true':
            is_one_to_many = True
        else:
            is_one_to_many = False

        if is_selfpaced.lower()=='true':
            is_selfpaced = True
        else:
            is_selfpaced = False


        if not is_selfpaced:
            if user_information.role=='OrgAdmin':
                is_organization = True
                organization = user_information.organization.id
            elif user_information.role=='Instructor':
                if user_information.is_organization:
                    is_organization = True
                    organization = user_information.organization.id
                else:
                    is_organization = False
                    organization = None

                if course_status == 'Approved':
                    return Response({'error': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)

            else:
                if is_organization.lower()=='true':
                    is_organization = True
                    try:
                        organization = int(organization)
                    except:
                        return Response({'error': 'Invalid organization id.'}, status=status.HTTP_400_BAD_REQUEST)
                else:
                    is_organization = False
                    organization = None

        if student_limit:
            try:
                student_limit = int(student_limit)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Student limit must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            student_limit = None

        # if not country_fees:
        #     return Response({'error': 'Please enter country fees.'}, status=status.HTTP_400_BAD_REQUEST)
        
        if user_information.role == 'Instructor':
            instructor = Instructor.objects.get(user=user)
            instructors = [instructor.id]

        for i in instructors:
            if not Instructor.objects.filter(id=i).exists():
                return Response({'status': False, 'data': None, 'msg': f'Instructor {i} not found'}, status=status.HTTP_404_NOT_FOUND)


        course = Course.objects.create(
            title=title,
            details=details,
            country_fees=country_fees,
            student_limit=student_limit,
            duration=duration,
            image=image,
            syllabus=syllabus, 
            start_date=start_date,
            end_date=end_date,
            group_discount=group_discount,
            grade_level=grade_level,
            education_type=education_type,
            grade_class=grade_class,
            is_one_to_one=is_one_to_one,
            is_one_to_group=is_one_to_group,
            is_one_to_many=is_one_to_many,
            is_selfpaced=is_selfpaced,
            is_organization=False,
            organization=organization,
            created_by=request.user,
            study_method=study_method,
            assessments=assessments,
            entry_requirements=entry_requirements,
            language=language,
            what_you_will_learn=what_you_will_learn,
            topics_covered=topics_covered,
            description=description,
            assessment_details=assessment_details,
            textbooks=textbooks,
            regarding_requirements=regarding_requirements,
            about_study_loans=about_study_loans,
            why_focus_on_one_subject=why_focus_on_one_subject,
            what_to_learn_next=what_to_learn_next,
            faq=faq,
            course_status=course_status
        )

        for s in subject:
            course.subject.add(i)

        for i in instructors:
            course.instructor.add(i)

        serializer = CourseSerializer(course)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course Created.'}, status=status.HTTP_201_CREATED)


class CourseDetail(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsInstructor | IsOrgAdmin]

    def get(self, request):
        try:
            course_id = int(request.GET.get('course_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Invalid course id.'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_404_NOT_FOUND)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_404_NOT_FOUND)

        serializer = CourseSerializer(course)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course fetched.'}, status=status.HTTP_200_OK)


    def put(self, request):
        course_id = int(request.data.get('course_id', 0))

        try:
            course_id = int(course_id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Course id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        title = request.data.get('title', None)
        details = request.data.get('details', None)
        country_fees = request.data.get('country_fees', None)
        group_discount = request.data.get('group_discount', None)
        student_limit = request.data.get('student_limit', None)
        duration = request.data.get('duration', None)
        start_date = request.data.get('start_date', None)
        end_date = request.data.get('end_date', None)    
        grade_level = request.data.get('organization', None)
        education_type = request.data.get('education_type', None)
        grade_class = request.data.get('grade_class', None)
        subject = request.data.get('subject', [])
        instructors = request.data.get('instructors', [])
        is_one_to_one = request.data.get('is_one_to_one', '')
        is_one_to_group = request.data.get('is_one_to_group', '')
        is_one_to_many = request.data.get('is_one_to_many', '')
        is_selfpaced = request.data.get('is_selfpaced', '')
        is_organization = request.data.get('is_organization', '')
        organization = request.data.get('organization', None)
        image = request.FILES.get('image', None)
        syllabus = request.FILES.get('syllabus', None)
        
        study_method = request.data.get('study_method', None)
        assessments = request.data.get('assessments', None)
        entry_requirements = request.data.get('entry_requirements', None)
        language = request.data.get('language', None)
        what_you_will_learn = request.data.get('what_you_will_learn', None)
        topics_covered = request.data.get('topics_covered', None)
        description = request.data.get('description', None)
        assessment_details = request.data.get('assessment_details', None)
        textbooks = request.data.get('textbooks', None)
        regarding_requirements = request.data.get('regarding_requirements', None)
        about_study_loans = request.data.get('about_study_loans', None)
        why_focus_on_one_subject = request.data.get('why_focus_on_one_subject', None)
        what_to_learn_next = request.data.get('what_to_learn_next', None)
        faq = request.data.get('faq', '')
        course_status = request.data.get('course_status', '')

        user = request.user
        user_information = user.userinformation

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title.'}, status=status.HTTP_400_BAD_REQUEST)

        if not detail:
            return Response({'status': False, 'data': None, 'msg': 'Please enter course details.'}, status=status.HTTP_400_BAD_REQUEST)

        if course_status not in ['Draft', 'Pending', 'Approved']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)

        if user_information.role=='Instructor' and course_status=='Approved':
            return Response({'status': False, 'data': None, 'msg': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)

        if duration:
            try:
                duration = int(duration)
            except:
                return Response({'error': 'Duration must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            duration = None

        if not grade_level:
            grade_level = None

        if not education_type:
            education_type = None

        if not grade_class:
            grade_class = None

        if subject:
            subject = json.loads(subject)
        else:
            subject = []

        if group_discount:
            try:
                group_discount = json.loads(group_discount)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid group discount JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            group_discount = None

        if country_fees:
            try:
                country_fees = json.loads(country_fees)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid country fees JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            country_fees = None

        if instructors:
            try:
                instructors = json.loads(instructors)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid instructor JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            instructors = None

        if faq:
            try:
                faq = json.loads(faq)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Invalid faq JSON format.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            faq = None

        if is_one_to_one.lower()=='true':
            is_one_to_one = True
        else:
            is_one_to_one = False

        if is_one_to_group.lower()=='true':
            is_one_to_group = True
        else:
            is_one_to_group = False

        if is_one_to_many.lower()=='true':
            is_one_to_many = True
        else:
            is_one_to_many = False

        if is_selfpaced.lower()=='true':
            is_selfpaced = True
        else:
            is_selfpaced = False

        if not is_selfpaced:
            if user_information.role=='OrgAdmin':
                is_organization = True
                organization = user_information.organization.id
            elif user_information.role=='Instructor':
                if user_information.is_organization:
                    is_organization = True
                    organization = user_information.organization.id
                else:
                    is_organization = False
                    organization = None

                if course_status == 'Approved':
                    return Response({'status': False, 'data': None, 'msg': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)
            else:
                if is_organization.lower()=='true':
                    is_organization = True
                    try:
                        organization = int(organization)
                    except:
                        return Response({'status': False, 'data': None, 'msg': 'Invalid organization.'}, status=status.HTTP_400_BAD_REQUEST)
                else:
                    is_organization = False
                    organization = None

        if student_limit:
            try:
                student_limit = int(student_limit)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Student limit must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            student_limit = None
        # if not country_fees:
        #     return Response({'error': 'Please enter country fees.'}, status=status.HTTP_400_BAD_REQUEST)    
        
        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        
        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
                
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_404_NOT_FOUND)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        
        if image:
            course.image = image

        if syllabus:
            course.syllabus = syllabus

        course.title = title
        course.details = details
        course.country_fees = country_fees
        course.student_limit = student_limit
        course.duration = duration
        course.start_date = start_date
        course.end_date = end_date
        course.group_discount = group_discount
        course.grade_level = grade_level
        course.education_type = education_type
        course.grade_class = grade_class
        course.instructors = instructors
        course.is_one_to_one = is_one_to_one
        course.is_one_to_group = is_one_to_group
        course.is_one_to_many = is_one_to_many
        course.is_selfpaced = is_selfpaced
        course.is_organization = False
        course.organization = organization
        course.study_method = study_method
        course.assessments = assessments
        course.entry_requirements = entry_requirements
        course.language = language
        course.what_you_will_learn = what_you_will_learn
        course.topics_covered = topics_covered
        course.description = description
        course.assessment_details = assessment_details
        course.textbooks = textbooks
        course.regarding_requirements = regarding_requirements
        course.about_study_loans = about_study_loans
        course.why_focus_on_one_subject = why_focus_on_one_subject
        course.what_to_learn_next = what_to_learn_next
        course.faq = faq
        course.course_status = course_status

        course.subject.clear()
        for s in subject:
            course.subject.add(s)

        if user_information.role != 'Instructor':
            course.instructor.clear()
            for i in instructors:
                course.instructor.add(i)

        course.save()

        serializer = CourseSerializer(course)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course updated.'}, status=status.HTTP_200_OK)


    def patch(self, request):
        user = request.user
        user_information = user.userinformation

        if user_information.role not in ['Admin', 'OrgAdmin']:
            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access'}, status=status.HTTP_401_UNAUTHORIZED)

        try:
            course_id = int(request.data.get('course_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Course id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        course_status = request.data.get('course_status', None)
        
        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if course_status not in ['Approved', 'Pending', 'Draft']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid course status.'}, status=status.HTTP_400_BAD_REQUEST)
        
        course.course_status = course_status
        course.save()
        
        return Response({'status': True, 'data': {'Course id': course_id, 'Course status': course_status}, 'msg': 'Course status updated.'}, status=status.HTTP_200_OK)


class CourseListMini(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsInstructor | IsOrgAdmin]

    def get(self, request):
        course_status = request.GET.get('course_status', '')

        user = request.user
        user_information = user.userinformation

        if user_information.role == 'Admin':
            courses = Course.objects.filter(course_status__icontains=course_status).order_by('-id')
        elif user_information.role == 'OrgAdmin':
            courses = Course.objects.filter(organization=user_information.organization, course_status_icontains=course_status).order_by('-id')
        else:
            instructor = Instructor.objects.get(user=user)
            courses = Course.objects.filter(instructor=instructor, course_status__icontains=course_status).order_by('-id')
        
        serializer = CourseSerializerMini(courses, many=True)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course list fetched.'}, status=status.HTTP_200_OK)


class CourseListMiniUnauth(APIView):
    permission_classes = []

    def get(self, request):
        courses = Course.objects.filter(course_status='Approved').order_by('-created_at')
        
        serializer = CourseSerializerMini(courses, many=True)

        return Response({'success': serializer.data}, status=status.HTTP_200_OK)


class StudentCourseMini(APIView): # For student card view
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = self.request.user
        course_list = UserCourse.objects.filter(user=user, approval_status='Approved')
        serializer = MiniCourseSerializer(course_list, many=True)

        return Response({'courses': serializer.data})


class AdminCourseMini(APIView): # For admin card view
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = self.request.user
        user_information = UserInformation.objects.get(user=user)

        session_id = request.GET.get('session_id', '')

        if session_id == '':
            course_list = Course.objects.all()
            if user_information.role == 'Admin':
                serializer = MiniCourseSerializerAdmin(course_list, many=True)

                return Response({'courses': serializer.data})
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)

        else:
            session_id = int(session_id)

            try:
                session = AcademicSession.objects.get(id=session_id)
            except AcademicSession.DoesNotExist:
                return Response({'error': 'Session not found.'}, status=status.HTTP_404_NOT_FOUND)

            if user_information.role == 'Admin':
                course_list = Course.objects.filter(academic_session=session)
                serializer = MiniCourseSerializerAdmin(course_list, many=True)

                return Response({'courses': serializer.data})
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)

    
class StudentCourseChecker(APIView):  # For student card view
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        course_id = request.GET.get('course_id')  # Fixed typo from `couese_id`

        if not course_id:
            return Response(
                {"error": "course_id parameter is required."},
                status=status.HTTP_400_BAD_REQUEST
            )

        is_enrolled = UserCourse.objects.filter(user=user, course=course_id).exists()

        enrollment_status = "Enrolled" if is_enrolled else "Not Enrolled"

        return Response({'status': enrollment_status})


class InstructorCoursesView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        academic_session_id = int(request.GET.get('session_id', 0))
        instructor_id = Instructor.objects.get(user=request.user)

        # Check if the user is authenticated
        if request.user.is_anonymous:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # Check if the user is an instructor
        if request.user.userinformation.role != 'Instructor':
            return Response(status=status.HTTP_401_UNAUTHORIZED)

        # Filter courses by academic session
        if academic_session_id == 0:  # No specific session, fetch all courses
            courses = Course.objects.filter(instructor=instructor_id)
        else:  # Filter by academic session
            courses = Course.objects.filter(
                instructor=instructor_id,
                academic_session_id=academic_session_id
            )

        # Fetch associated UserCourse (sections) for the courses
        course_ids = courses.values_list('id', flat=True)
        user_courses = UserCourse.objects.filter(course_id__in=course_ids, approval_status='Approved', instructor=instructor_id)

        # Serialize the sections (UserCourse)
        serializer = MiniCourseSerializer(user_courses, many=True)

        return Response({'courses': serializer.data}, status=status.HTTP_200_OK)


class StudentCourseSuggested(APIView): # For student suggested view
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = self.request.user
        enrolled_courses = UserCourse.objects.filter(user=user).values_list('course_id', flat=True)
        suggested_courses = Course.objects.exclude(id__in=enrolled_courses)
        serializer = SuggestedCourseSerializer(suggested_courses, many=True)

        return Response({'courses': serializer.data})


# class CourseDetails(APIView):  # For student view
#     permission_classes = [IsAuthenticated]

#     def get(self, request, **kwargs):
#         section = kwargs['id']
#         remaining_subscriptions = 0
#         total_subsc = 0
        
#         try:
#             if request.user.userinformation.role == 'Instructor':
#                 # Fetch instructor's course
#                 instructor_id = Instructor.objects.get(user=request.user)
#                 user_course = UserCourse.objects.get(instructor=instructor_id, id=section, approval_status='Approved')
            
#             elif request.user.userinformation.role == 'Student':
#                 # Fetch student's course
#                 user_course = UserCourse.objects.get(user=request.user.id, id=section, approval_status='Approved')
#                 if UserCourse.objects.filter(user=request.user.id, id=section, approval_status='Approved').exists():
#                     course_payment = CoursePayment.objects.filter(user=request.user).first()
#                     if course_payment:
#                         # Count the number of courses the user is currently enrolled in for the given section
#                         enrolled_courses_count = UserCourse.objects.filter(id=section, approval_status='Approved').count()
#                         # Calculate the remaining subscriptions
#                         remaining_subscriptions = course_payment.no_of_subscriptions - enrolled_courses_count
#                         total_subsc = course_payment.no_of_subscriptions if course_payment.no_of_subscriptions else None,
                        
            
#             # Retrieve course details
#             course = Course.objects.get(id=user_course.course.id, is_archived=False)
#         except ObjectDoesNotExist:
#             return Response({'message': 'You are not authorized or the course does not exist.'}, status=status.HTTP_404_NOT_FOUND)

#         # Prepare course data to be returned
#         course_serializer = {
#             'details': course.details,
#             'course_why_choose': course.course_why_choose,
#             'banner': course.image.url if course.image else None,
#             'can_invite': remaining_subscriptions,
#             'total_subsc': total_subsc,
#             'user': [
#                 {
#                     'id': user.id,
#                     'full_name': user.userinformation.full_name,  # Adjust based on your User model's fields
#                     'email': user.email,
#                     'image': user.userinformation.image.url if user.userinformation.image else None
#                 }
#                 for user_course in UserCourse.objects.filter(course=course, id=section)
#                 for user in user_course.user.all()  # Assuming `user` is a ManyToManyField
#             ]
#         }

#         # If you have any additional logic based on can_invite, you can handle it here

#         return Response(course_serializer, status=status.HTTP_200_OK)


class CourseDetailsUnauth(APIView):
    permission_classes = []

    def get(self, request):
        id = request.GET.get('id', None)
        try:
            course = Course.objects.get(id=id, is_archived=False)
        except Course.DoesNotExist:
            return Response({"detail": "No courses found."},status=status.HTTP_404_NOT_FOUND)

        course_serializer = CourseSerializer(course)
        
        # Call the TestimonialList view and get testimonials data
        testimonials_view = TestimonialList(course_id=id)
        testimonials_response = testimonials_view.get(request)  # Pass course_id here
        testimonials_data = testimonials_response.data  # Access data from the Response object

        # Combine the course data and testimonials data
        combined_data = {
            "course_data": course_serializer.data,
            "testimonials_data": testimonials_data
        }

        return Response(combined_data, status=status.HTTP_200_OK)


class InstructorCourseList(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, **kwargs):
        academic_session_id = kwargs['academic_session_id']

        if request.user.is_anonymous:
            return Response(status=status.HTTP_404_NOT_FOUND)
        else:
            if request.user.userinformation.role == 'Instructor':
                if academic_session_id == 0:
                    courses = Course.objects.filter(
                        instructor=request.user.instructor)
                else:
                    courses = Course.objects.filter(
                        instructor=request.user.instructor, academic_session_id=academic_session_id)
                serializer = CourseSerializer(courses, many=True)

                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)


class CourseContentMinList(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, **kwargs):
        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                course_id = kwargs['course_id']

                course = Course.objects.get(id=course_id)
                course_contents = CourseContent.objects.filter(course=course)
                serializer = CourseContentMinSerializer(
                    course_contents, many=True)

                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)


class CourseContentList(APIView):  # For Admin, OrgAdmin and Instructor
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        try:
            course_id = int(request.GET.get('course_id', 0))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Course id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        course_contents = CourseContent.objects.filter(course=course).order_by('sequence')
        coursecontent_serializer = CourseContentSerializer(course_contents, many=True)

        return Response({'status': True, 'data': coursecontent_serializer.data, 'msg': 'Course content list fetched.'}, status=status.HTTP_200_OK)

    def post(self, request):
        title = request.data.get('title', '')

        try:
            course_id = int(request.data.get('course_id', 0))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Invalid course id. Course id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            sequence = int(request.data.get('sequence', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Invalid sequence. Sequence must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title.'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            
        course_content = CourseContent.objects.create(sequence=sequence, course=course, title=title, created_by=user)
        course_content_serializer = CourseContentSerializer(course_content)

        return Response({'status': True, 'data': course_content_serializer.data, 'msg': 'Course content created.'}, status=status.HTTP_201_CREATED)


class CourseContentDetails(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        try:
            content_id = int(request.GET.get('content_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Content id must be an integer'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            course_content = CourseContent.objects.get(id=content_id)
        except CourseContent.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course content not found.'}, status=status.HTTP_404_NOT_FOUND)

        user = request.user
        user_information = user.userinformation
        course = course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)


        serializer = CourseContentSerializer(course_content)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course content fetched.'}, status=status.HTTP_200_OK)

    def put(self, request):
        title = request.data.get('title', '')

        try:
            sequence = int(request.data.get('sequence', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Sequence must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            content_id = int(request.data.get('content_id', 0))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Content id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            course_content = CourseContent.objects.get(id=content_id)
        except CourseContent.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course content not found.'}, status=status.HTTP_404_NOT_FOUND)

        user = request.user
        user_information = user.userinformation
        course = course_content.course

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title.'}, status=status.HTTP_400_BAD_REQUEST)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)


        course_content.title = title
        course_content.sequence = sequence
        course_content.save()

        serializer = CourseContentSerializer(course_content)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course content updated.'}, status=status.HTTP_200_OK)


    def delete(self, request):
        try:
            content_id = int(request.data.get('content_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Content id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        try:
            course_content = CourseContent.objects.get(id=content_id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Course content not found.'}, status=status.HTTP_404_NOT_FOUND)

        course = course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        course_content.delete()

        return Response({'status': True, 'data': None, 'msg': 'Course content deleted.'}, status=status.HTTP_200_OK)


class CourseContentElementList(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        try:
            content_id = int(request.GET.get('content_id', 0))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Content id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        try:
            course_content = CourseContent.objects.get(id=content_id)
        except CourseContent.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course content not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        course = course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        
        video = Video.objects.filter(course_content=course_content)
        video_serializer = CourseContentVideoSerializer(video, many=True)
        
        document = CourseContentDocument.objects.filter(course_content=course_content)
        document_serializer = CourseContentDocumentSerializer(document, many=True)

        all_data = video_serializer.data + document_serializer.data

        all_data = sorted(all_data, key=lambda item: item['sequence'])
        
        return Response({'status': True, 'data': all_data, 'msg': 'Course content element list fetched.'}, status=status.HTTP_200_OK)

    def post(self, request):
        try:
            content_id = int(request.data.get('content_id', 0))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Content id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            sequence = int(request.data.get('sequence', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Sequence must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        
        file = request.FILES.get('file', None)
        file_type = request.data.get('file_type', None)
        title = request.data.get('title', None)

        if file_type not in ['video', 'document']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid file type'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        try:
            course_content = CourseContent.objects.get(id=content_id)
        except CourseContent.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Course content not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        course = course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if not file:
            if file_type == 'video':
                return Response({'status': False, 'data': None, 'msg': 'Upload a video file.'}, status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response({'status': False, 'data': None, 'msg': 'Upload a document file.'}, status=status.HTTP_400_BAD_REQUEST)

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title'}, status=status.HTTP_400_BAD_REQUEST)

        if file_type == 'video':
            video = Video.objects.create(sequence=sequence, course_content=course_content, title=title, file=file, created_by=user)
            serializer = CourseContentVideoSerializer(video)
        else:
            document = CourseContentDocument.objects.create(sequence=sequence, course_content=course_content, title=title, file=file, created_by=user)
            serializer = CourseContentDocumentSerializer(document)

        
        return Response({'status': True, 'data': serializer.data, 'msg': 'Course content element fetched.'}, status=status.HTTP_201_CREATED)


class CourseContentElementDetails(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        try:
            element_id = int(request.GET.get('element_id', None))
        except:
            return Response({'status': False, 'data': True, 'msg': 'Element id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        
        file_type = request.GET.get('file_type', None)

        if file_type not in ['video', 'document']:
            return Response({'status': False, 'data': False, 'msg': 'Invalid file type'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        if file_type == 'video':
            try:
                video = Video.objects.get(id=element_id)
            except Video.DoesNotExist:
                return Response({'status': False, 'data': None, 'msg': 'Video element not found.'}, status=status.HTTP_404_NOT_FOUND)

            course = video.course_content.course
            serializer = CourseContentVideoSerializer(video)
        else:
            try:
                document = CourseContentDocument.objects.get(id=element_id)
            except CourseContentDocument.DoesNotExist:
                return Response({'status': False, 'data': None, 'msg': 'Document element not found.'}, status=status.HTTP_404_NOT_FOUND)

            course = document.course_content.course
            serializer = CourseContentDocumentSerializer(document)

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course content element fetched.'}, status=status.HTTP_200_OK)

    def put(self, request):
        try:
            sequence = int(request.data.get('sequence', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Sequence must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            element_id = int(request.data.get('element_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Element id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        
        file = request.FILES.get('file', None)
        file_type = request.data.get('file_type', None)
        title = request.data.get('title', None)

        if file_type not in ['video', 'document']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid file type'}, status=status.HTTP_400_BAD_REQUEST)

        
        if file_type == 'video':
            try:
                video = Video.objects.get(id=element_id)
            except Video.DoesNotExist:
                return Response({'status': False, 'data': None, 'msg': 'Video element not found.'}, status=status.HTTP_404_NOT_FOUND)

            course = video.course_content.course
        else:
            try:
                document = CourseContentDocument.objects.get(id=element_id)
            except CourseContentDocument.DoesNotExist:
                return Response({'status': False, 'data': None, 'msg': 'Document element not found.'}, status=status.HTTP_404_NOT_FOUND)

            course = document.course_content.course

        user = request.user
        user_information = user.userinformation

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title'}, status=status.status.HTTP_400_BAD_REQUEST)

        if file_type == 'video':
            if file:
                video.file = file
            
            video.sequence = sequence
            video.title = title
            video.save()

            serializer = CourseContentVideoSerializer(video)
        else:
            if file:
                document.file = file
            
            document.sequence = sequence
            document.title = title
            document.save()

            serializer = CourseContentDocumentSerializer(document)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course content element updated.'}, status=status.HTTP_200_OK)


    def delete(self, request):
        try:
            element_id = int(request.data.get('element_id', 0))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Element id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        file_type = request.data.get('file_type', None)
        
        if file_type not in ['video', 'document']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid file type'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_information = user.userinformation

        if file_type == 'video':
            try:
                video = Video.objects.get(id=element_id)
            except Video.DoesNotExist:
                return Response({'status': False, 'data': None, 'msg': 'Video element not found.'}, status=status.HTTP_404_NOT_FOUND)

            course = video.course_content.course
        else:
            try:
                document = CourseContentDocument.objects.get(id=element_id)
            except CourseContentDocument.DoesNotExist:
                return Response({'status': False, 'data': None, 'msg': 'Document element not found.'}, status=status.HTTP_404_NOT_FOUND)

            course = document.course_content.course
    

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if file_type == 'video':
            video.delete()
        else:
            document.delete()

        return Response({'status': False, 'data': None, 'msg': 'Course content element deleted.'}, status=status.HTTP_200_OK)


class CourseContentResourceList(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        try:
            video_id = int(request.GET.get('video_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Video id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            video = Video.objects.get(id=video_id)
        except Video.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Video not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        user = request.user
        user_information = user.userinformation
        course = video.course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        resource = CourseContentResource.objects.filter(video=video).order_by('sequence')
        serializer = CourseContentResourceSerializer(resource, many=True)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Course content resource list fetched.'}, status=status.HTTP_200_OK)

    def post(self, request):
        file = request.FILES.get('file', None)
        file_type = request.data.get('file_type', '')
        title = request.data.get('title', None)

        if file_type != 'video':
            return Response({'status': False, 'data': None, 'msg': 'Resource can be uploaded only for video elements.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            video_id = int(request.data.get('video_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Video id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            sequence = int(request.data.get('sequence', None))
        except:
            return Response({'msg': 'Sequence must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            video = Video.objects.get(id=video_id)
        except Video.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Video not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        user = request.user
        user_information = user.userinformation
        course = video.course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if not file:
            return Response({'status': False, 'data': None, 'msg': 'Please upload a resource file.'}, status=status.HTTP_400_BAD_REQUEST)

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title.'}, status=status.HTTP_400_BAD_REQUEST)

        resource = CourseContentResource.objects.create(sequence=sequence, title=title, video=video, file=file, created_by=user)
        serializer = CourseContentResourceSerializer(resource)

        return Response({'status': True, 'data': serializer.data, 'msg': 'Resource created.'}, status=status.HTTP_201_CREATED)


class CourseContentResourceDetails(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        try:
            resource_id = int(request.GET.get('resource_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Resource id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            resource = CourseContentResource.objects.get(id=resource_id)
        except CourseContentResource.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Resource not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        user = request.user
        user_information = user.userinformation
        course = resource.video.course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        serializer = CourseContentResourceSerializer(resource)

        return Response({'status': False, 'data': serializer.data, 'msg': 'Resource fetched.'}, status=status.HTTP_200_OK)

    def put(self, request):
        file = request.FILES.get('file', None)
        title = request.data.get('title', None)
        
        try:
            sequence = int(request.data.get('sequence', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Sequence must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            resource_id = int(request.data.get('resource_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Resource id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            resource = CourseContentResource.objects.get(id=resource_id)
        except CourseContentResource.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Resource not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        user = request.user
        user_information = user.userinformation
        course = resource.video.course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if not title:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a title.'}, status=status.HTTP_400_BAD_REQUEST)

        if file:
            resource.file = file

        resource.sequence = sequence
        resource.title = title
        resource.save()

        serializer = CourseContentResourceSerializer(resource)

        return Response({'status': False, 'data': serializer.data, 'msg': 'Resource updated.'}, status=status.HTTP_200_OK)

    def delete(self, request):
        try:
            resource_id = int(request.data.get('resource_id', None))
        except:
            return Response({'status': False, 'data': None, 'msg': 'Resource id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            resource = CourseContentResource.objects.get(id=resource_id)
        except CourseContentResource.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Resource not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        user = request.user
        user_information = user.userinformation
        course = resource.video.course_content.course

        if user_information.role == 'OrgAdmin':
            # Check if OrgAdmin has access to the organization
            if course.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if user_information.role == 'Instructor':
            if user_information.is_organization is True: 
                # Check if instructor has access to the organization and course
                if course.organization.id != user_information.organization.id:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                # Check if non organization instructor has access to the course
                if not course.instructor.filter(id=user.instructor.id).exists():
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        resource.delete()

        return Response({'status': True, 'data': None, 'msg': 'Resource deleted.'}, status=status.HTTP_200_OK)


class CourseLectureNote(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request, **kwargs):  # Create lecture note
        id = kwargs['id']
        #title = kwargs['title']
        lecture_note = request.data['lecture_note']
        title = request.data['title']
        try:
            course_content = CourseContent.objects.get(id=id)
        except CourseContent.DoesNotExist:
            course_content = None

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                if course_content:
                    lecturenote = LectureNote.objects.create(
                        coursecontent=course_content,
                        title=title,
                        file=lecture_note
                    )

                    # Notify students using email
                    # students = course_content.course.student.all()
                    # for student in students:
                    #     send_mail(
                    #         'Lecture Note Upload',
                    #         'Lecture note has been uploaded to your enrolled course ' +
                    #         '"' + course_content.course.title + '"' + ' for week ' + str(course_content.week)
                    #         + '\n'
                    #         + 'Please visit this course from your "My Learnings" section to see the lecture note.'
                    #         + '\n \n'
                    #         + 'Best Regards'
                    #         + '\n'
                    #         + 'QA Tek Admin',
                    #         'qatek.lms@gmail.com',
                    #         [student.email],
                    #         fail_silently=False,
                    #     )

                    serializer = LectureNoteSerializer(lecturenote)

                    return Response(serializer.data, status=status.HTTP_201_CREATED)
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, request, **kwargs):
        id = kwargs['id']

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor']:
                try:
                    lecturenote = LectureNote.objects.get(id=id)
                    lecturenote.delete()

                    return Response(status=status.HTTP_202_ACCEPTED)
                except LectureNote.DoesNotExist:
                    return Response(status=status.HTTP_404_NOT_FOUND)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)


class CourseHomework(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request, **kwargs):  # Create homework
        id = kwargs['id']
        #title = kwargs['title']
        homework = request.data['homework']
        title = request.data['title']
        try:
            course_content = CourseContent.objects.get(id=id)
        except CourseContent.DoesNotExist:
            course_content = None

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                if course_content:
                    homework = Homework.objects.create(
                        coursecontent=course_content,
                        title=title,
                        file=homework
                    )

                    # Notify students using email
                    # students = course_content.course.student.all()
                    # for student in students:
                    #     send_mail(
                    #         'New Homework Upload',
                    #         'A new homework has been uploaded to your enrolled course ' +
                    #         '"' + course_content.course.title + '"' + ' for week ' + str(course_content.week)
                    #         + '\n'
                    #         + 'Please visit this course from your "My Learnings" section to see the homework file.'
                    #         + '\n \n'
                    #         + 'Note: Submit the homework file/ files in time'
                    #         + '\n \n'
                    #         + 'Best Regards'
                    #         + '\n'
                    #         + 'QA Tek Admin',
                    #         'qatek.lms@gmail.com',
                    #         [student.email],
                    #         fail_silently=False,
                    #     )

                    serializer = HomeworkSerializer(homework)

                    return Response(serializer.data, status=status.HTTP_201_CREATED)
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, request, **kwargs):
        id = kwargs['id']

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                try:
                    homework = Homework.objects.get(id=id)
                    homework.delete()

                    return Response(status=status.HTTP_202_ACCEPTED)
                except Homework.DoesNotExist:
                    return Response(status=status.HTTP_404_NOT_FOUND)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)


class CourseHomeworkSubmission(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, **kwargs):  # Create homework submission
        id = kwargs['id']
        #title = kwargs['title']
        homeworksubmission = request.data['homeworksubmission']
        title = request.data['title']
        try:
            course_content = CourseContent.objects.get(id=id)
        except CourseContent.DoesNotExist:
            course_content = None

        if course_content:
            homeworksubmission = HomeworkSubmission.objects.create(
                coursecontent=course_content,
                student=self.request.user,
                title=title,
                file=homeworksubmission
            )

            # Create model instance for new comment notification
            instructors = homeworksubmission.coursecontent.course.instructor.all()
            for instructor in instructors:
                try:
                    if not HomeworkSubNewComment.objects.filter(homeworksubmission=homeworksubmission, user=instructor.user).exists():
                        HomeworkSubNewComment.objects.create(
                            homeworksubmission=homeworksubmission,
                            user=instructor.user
                        )
                except Exception as e:

                    if not HomeworkSubNewComment.objects.filter(homeworksubmission=homeworksubmission, user=request.user).exists():
                        HomeworkSubNewComment.objects.create(
                            homeworksubmission=homeworksubmission,
                            user=request.user
                        )

            # Notify instructors sending email
            # instructors = course_content.course.instructor.all()
            # for instructor in instructors:
            #     send_mail(
            #         'Homework Submission',
            #         f'{self.request.user.first_name} {self.response.user.last_name}' +
            #         ' has submitted week ' + str(course_content.week) + ' homework of' + '"' + course_content.course.title + '"'
            #         + '\n'
            #         + 'Please visit this course from your "My Course" section to see the submitted homework file.'
            #         + '\n \n'
            #         + 'Best Regards'
            #         + '\n'
            #         + 'QA Tek Admin',
            #         'qatek.lms@gmail.com',
            #         [instructor.email],
            #         fail_silently=False,
            #     )

            # Notify admins sending email
            # admins = User.objects.filter(userinformation_role='Admin')
            # for admin in admins:
            #     send_mail(
            #         'Homework Submission',
            #         f'{self.request.user.first_name} {self.response.user.last_name}' +
            #         ' has submitted week ' + str(course_content.week) + ' homework of' + '"' + course_content.course.title + '"'
            #         + '\n'
            #         + 'Please visit this course from your "Courses" section to see the submitted homework file.'
            #         + '\n \n'
            #         + 'Best Regards'
            #         + '\n'
            #         + 'QA Tek Admin',
            #         'qatek.lms@gmail.com',
            #         [admin.email],
            #         fail_silently=False,
            #     )

            serializer = HomeworkSubmissionSerializer(homeworksubmission)

            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, **kwargs):
        id = kwargs['id']

        try:
            homeworksubmission = HomeworkSubmission.objects.get(id=id)
            homeworksubmission.delete()

            return Response(status=status.HTTP_202_ACCEPTED)
        except HomeworkSubmission.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)


class StudentCourseList(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, **kwargs):
        academic_session_id = kwargs['academic_session_id']

        if self.request.user.is_anonymous:
            courses = None
        else:
            if academic_session_id == 0:
                usercourses = UserCourse.objects.filter(user=self.request.user, hold_access=False)
            else:
                usercourses = UserCourse.objects.filter(user=self.request.user, course__academic_session_id=academic_session_id, hold_access=False)

            courses = [usercourse.course for usercourse in usercourses]

        serializer = CourseSerializer(courses, many=True)

        return Response(serializer.data, status=status.HTTP_200_OK)


class CourseStatus(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request, **kwargs):
        id = kwargs['id']
        data = json.loads(request.body)

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor']:
                course = Course.objects.get(id=id)
                course.is_active = data['status']
                course.save()

                return Response(status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)


class StudentHomeworkSubmission(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, **kwargs):
        coursecontent_id = kwargs['coursecontent_id']

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                coursecontent = CourseContent.objects.get(id=coursecontent_id)
                students = coursecontent.course.student.all()
                serializer = StudentHomeworkSubmissionSerializer(
                    students, many=True, context={'coursecontent': coursecontent, 'user': request.user})

                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)


class StudentHomeworkSubReview(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, **kwargs):
        homeworksubreview = request.data['homeworksubreview']
        title = request.data['title']
        coursecontent_id = request.data['coursecontent_id']
        student_id = request.data['student_id']

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                homeworksubreview = HomeworkSubReview.objects.create(
                    coursecontent_id=coursecontent_id,
                    student_id=student_id,
                    title=title,
                    file=homeworksubreview
                )

                serializer = HomeworkSubReviewSerializer(homeworksubreview)

                return Response(serializer.data, status=status.HTTP_201_CREATED)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def delete(self, request, **kwargs):
        data = json.loads(request.body)
        id = data['id']

        try:
            homeworksubreview = HomeworkSubReview.objects.get(id=id)
            homeworksubreview.delete()

            return Response(status=status.HTTP_202_ACCEPTED)
        except HomeworkSubReview.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)


class CourseDetailsAdminView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        id = request.GET.get('id', None)
        user = self.request.user
        user_information = UserInformation.objects.get(user=user)
       
        try:
            course = Course.objects.get(id=id)
        except Course.DoesNotExist:
            course = None

        if not user.is_anonymous:
            if user_information.role in ['Admin', 'AdminInstructor']:
                if course:
                    serializer = CourseSerializer(course)

                    return Response({'role': user.userinformation.role, 'course': serializer.data}, status=status.HTTP_200_OK)
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

    def put(self, request):
        user = self.request.user
        user_information = UserInformation.objects.get(user=user)

        # ids = request.data['id']
        # title = request.data['title']
        # details = request.data['details']
        # duration = int(float(request.data['duration']))
        # fee=request.data['fee']
        # image = request.data['image']
        # academic_session_id = request.data['academic_session_id']


        academic_session_id = request.data['session_id']
        course_id = request.data['course_id']
        title=request.data['title']
        age_group=request.data['age_group']
        details=request.data['details']
        course_cont_highlight=json.loads(request.data['course_cont_highlight'])
        course_level=json.loads(request.data['course_level'])
        course_prerequisites=json.loads(request.data['course_prerequisites'])
        course_why_choose=json.loads(request.data['course_why_choose'])
        country_fees=json.loads(request.data['country_fees'])
        duration=request.data['duration']
        student_limit=request.data['student_limit']
        number_class=request.data['number_class']
        # fee=request.data['fee'],
        image=request.data.get('image', '')
        syllabus=request.data.get('syllabus', '')
        # start_date=datetime.datetime.strptime(request.data['start_date'], '%Y-%m-%d').date()
        # end_date=datetime.datetime.strptime(request.data['end_date'], '%Y-%m-%d').date()
        start_date=request.data['start_date']
        end_date=request.data['end_date']
        group_discount=json.loads(request.data['group_discount'])
        course_days=json.loads(request.data['course_days'])

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response({'error': 'Course not found'}, status=status.HTTP_400_BAD_REQUEST)

        # if not user.is_anonymous and user_information.role in ['Admin', 'AdminInstructor', 'Instructor']:
        #     # Update only fields present in request.data
        #     if 'title' in request.data:
        #         course.title = request.data['title']
            
        #     if 'details' in request.data:
        #         course.details = request.data['details']
            
        #     if 'duration' in request.data:
        #         course.duration = int(float(request.data['duration']))
            
        #     if 'fee' in request.data:
        #         course.country_fee = request.data['fee']
            
        #     if 'image' in request.data and request.data['image'] != '':
        #         course.image = request.data['image']
            
        #     if 'academic_session_id' in request.data:
        #         course.academic_session_id = request.data['academic_session_id']

        if not user.is_anonymous:
            if user_information.role == 'Admin':
                if course:
                    course.title = title
                    course.age_group = age_group
                    course.details = details
                    course.duration = duration
                    course.course_cont_highlight = course_cont_highlight
                    course.course_prerequisites = course_prerequisites
                    course.course_level = course_level
                    course.course_why_choose = course_why_choose
                    course.country_fees = country_fees
                    course.student_limit = student_limit
                    course.number_class = number_class
                    course.start_date = start_date
                    course.end_date = end_date
                    course.group_discount = group_discount
                    course.course_days = course_days


                    # course.fee = fee
                    try: 
                        academic_session = AcademicSession.objects.get(id=academic_session_id)
                    except AcademicSession.DoesNotExist:
                        return Response({'error': 'Academic Session not found'}, status=status.HTTP_404_NOT_FOUND)

                    course.academic_session = academic_session
                    if image != '' and image != None and image != 'null':
                        course.image = image

                    if syllabus != '' and syllabus != None and syllabus != 'null':
                        
                        course.syllabus = syllabus 

                    course_instructors = course.instructor.all()
                    for course_instructor in course_instructors:
                        course.instructor.remove(course_instructor)
                    instructor_ids = json.loads(request.data['instructor'])
                    for instructor_id in instructor_ids:
                        try:
                            instructor = Instructor.objects.get(id=instructor_id['id'])
                            course.instructor.add(instructor)
                        except Instructor.DoesNotExist:
                            continue

                    course.save()
                    # serializer = CourseSerializer(course)

                    return Response({'status': 'Course updated successfully.'}, status=status.HTTP_200_OK)
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        return Response(status=status.HTTP_401_UNAUTHORIZED)

    
    def delete(self, request):
        user = request.user
        user_information = UserInformation.objects.get(user=user)
        
        if user_information.role != 'Admin':
            return Response(status=status.HTTP_401_UNAUTHORIZED)

        course_id = request.data.get('course_id', '')
        
        if course_id == '' or course_id == None:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        course_id = int(course_id)

        try:
            course = Course.objects.get(id=course_id)
        except Course.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        course.delete()

        return Response(status=status.HTTP_200_OK)

    def patch(self, request):
        data = request.data
        id = data.get('id', None)
        key = data.get('key', None)
        value = data.get('value', None)
        user = self.request.user
        user_information = UserInformation.objects.get(user=user)

        try:
            course = Course.objects.get(id=id)
        except Course.DoesNotExist:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        if not user_information.role in ['Admin', 'AdminInstructor', 'Instructor']:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

        if key == 'title':
            course.title = value
        elif key == 'details':
            course.details = value
        elif key == 'image':
            course.image = value
        elif key == 'is_active':
            course.is_active = value
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        course.save()

        serializer = CourseSerializer(course)

        return Response(serializer.data, status=status.HTTP_200_OK)


class AcademicSessionList(APIView):
    permission_classes = []

    def get(self, request):
        academic_sessions = AcademicSession.objects.all()
        serializer = AcademicSessionSerializer(academic_sessions, many=True)

        return Response(serializer.data)


class AuthAcademicSessionList(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        search = request.GET.get('search', '')
        offset = int(request.GET.get('offset', 0))
        limit = int(request.GET.get('limit', 10))

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor']:
                count = AcademicSession.objects.filter(
                    Q(title__trigram_word_similar=search) |
                    Q(title__icontains=search)
                ).count()

                academic_sessions = AcademicSession.objects.filter(
                    Q(title__trigram_word_similar=search) |
                    Q(title__icontains=search)
                )[offset:limit]

                serializer = AcademicSessionSerializer(academic_sessions, many=True)

                return Response({'session_data': serializer.data, 'total_sessions': count}, status=status.HTTP_200_OK)
            else:
                return Response({'error': 'Unauthorized Access.'}, status=status.HTTP_401_UNAUTHORIZED)

        return Response({'error': 'Unauthorized Access.'}, status=status.HTTP_401_UNAUTHORIZED)


class AuthAcademicSessionListMini(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        academic_sessions = AcademicSession.objects.all()

        serializer = AcademicSessionSerializerMini(academic_sessions, many=True)

        return Response({'session_data': serializer.data}, status=status.HTTP_200_OK)


class AcademicSessionDetails(APIView):
    permission_classes = [IsAuthenticated, IsAdmin]

    def post(self, request,  **kwargs):
        data = json.loads(request.body)
        title = data['title']
        details = data['details']

        if len(title) > 128:
            return Response({'error': 'Title cannot be more than 128 characters'}, status=status.HTTP_400_BAD_REQUEST)

        if len(details) > 2000:
            return Response({'error': 'Details cannot be more than 2000 characters'}, status=status.HTTP_400_BAD_REQUEST)

        if AcademicSession.objects.filter(title=title).exists():
            return Response({'error': 'A session with this title already exists.'}, status=status.HTTP_400_BAD_REQUEST)            
        else:
            academic_session = AcademicSession.objects.create(
                title=title,
                details=details,
            )
            return Response({'success': 'Session added successfully'}, status=status.HTTP_201_CREATED)

        return Response({'error': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

    def delete(self, request):
        data = json.loads(request.body)
        ids = data.get('selected_sessions', '')
        error = 'No Error'
        
        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor']:
                count = 0
                for id in ids:
                    try:
                        academic_session = AcademicSession.objects.get(id=id)
                        academic_session.delete()
                    except AcademicSession.DoesNotExist:
                        error = 'User Not Found'
                        continue
                    count = count + 1

                session_multiple = 'sessions'
                if count < 2:
                    session_multiple = 'session'

                return Response({'success': f'{count} {session_multiple} deleted', 'error': error}, status=status.HTTP_200_OK)
            else:
                error = 'Unauthorized access.'
                return Response({'error': error}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            error = 'Admin user not found'
            return Response({'error': error}, status=status.HTTP_404_NOT_FOUND)


class CourseArchival(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        course_id = request.data.get('course_id', None)
        is_archived = request.data.get('is_archived', None)

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor']:
                course = Course.objects.get(id=course_id)
                if is_archived == True:
                    try:
                        shutil.make_archive(f'{get_parent_directory(settings.BASE_DIR)}/course_archive_{course.id}', 'zip', settings.BASE_DIR / 'media' / course.academic_session.title / course.title)
                        shutil.rmtree(settings.BASE_DIR / 'media' / course.academic_session.title / course.title)

                        course.is_archived = is_archived
                        course.save()

                        return Response(status=status.HTTP_202_ACCEPTED)
                    except FileNotFoundError:
                        return Response({"message": "Directory not found."}, status=status.HTTP_400_BAD_REQUEST)
                elif is_archived == False:
                    try:
                        shutil.unpack_archive(f'{get_parent_directory(settings.BASE_DIR)}/course_archive_{course.id}.zip', settings.BASE_DIR / 'media' / course.academic_session.title / course.title, 'zip')
                        os.remove(f'{get_parent_directory(settings.BASE_DIR)}/course_archive_{course.id}.zip')

                        course.is_archived = is_archived
                        course.save()

                        return Response(status=status.HTTP_202_ACCEPTED)
                    except shutil.ReadError:
                        return Response({"message": "Zip file not found."}, status=status.HTTP_400_BAD_REQUEST)
                else:
                    return Response(status=status.HTTP_400_BAD_REQUEST)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        return Response(status=status.HTTP_401_UNAUTHORIZED)


class HomeworkDeadline(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        data = json.loads(request.body)
        coursecontent_id = data['id']
        date_time = data['date_time']

        if not request.user.is_anonymous:
            if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
                coursecontent = CourseContent.objects.get(id=coursecontent_id)
                coursecontent.homework_deadline = dateutil.parser.parse(date_time) if date_time else None
                coursecontent.save()

                serializer = CourseContentSerializer(coursecontent)

                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        return Response(status=status.HTTP_401_UNAUTHORIZED)


class HomeworkSubCommentList(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, **kwargs):
        homeworksubmission_id = kwargs['id']

        homeworksubcomments = HomeworkSubComment.objects.filter(homeworksubmission_id=homeworksubmission_id).order_by("id")
        serializer = HomeworkSubCommentSerializer(homeworksubcomments, many=True, context={'user': request.user})

        # Set comment seen flag=True
        try:
            if HomeworkSubNewComment.objects.filter(homeworksubmission_id=homeworksubmission_id, user=request.user).exists():
                homeworksubnewcomment = HomeworkSubNewComment.objects.get(homeworksubmission_id=homeworksubmission_id, user=request.user)
                homeworksubnewcomment.is_seen = True
                homeworksubnewcomment.save()
            else:
                HomeworkSubNewComment.objects.create(
                    homeworksubmission_id=homeworksubmission_id,
                    user=request.user,
                    is_seen=True
                )
        except Exception as e:
            return Response({"error": str(e)}, status=500)

        return Response(serializer.data)


class HomeworkSubCommentDetails(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        data = json.loads(request.body)
        text = data['text']
        homeworksubmission_id = data['id']

        homeworksubcomment = HomeworkSubComment.objects.create(
            homeworksubmission_id=homeworksubmission_id,
            text=text,
            comment_by=request.user
        )

        # Add seen=False flag to new comment notify models
        instructors = homeworksubcomment.homeworksubmission.coursecontent.course.instructor.all()
        instructors.exclude(user=request.user)
        student = homeworksubcomment.homeworksubmission.student
        for instructor in instructors:
            try:
                if HomeworkSubNewComment.objects.filter(homeworksubmission=homeworksubcomment.homeworksubmission, user=instructor.user).exists():
                    homeworksubnewcomment = HomeworkSubNewComment.objects.get(homeworksubmission=homeworksubcomment.homeworksubmission, user=instructor.user)
                    homeworksubnewcomment.is_seen = False
                    homeworksubnewcomment.save()
                else:
                    HomeworkSubNewComment.objects.create(
                        homeworksubmission=homeworksubcomment.homeworksubmission,
                        user=instructor.user,
                        is_seen=False
                    )
            except Exception as e:
                return Response({"error": str(e)}, status=500)

        if student != request.user:
            try:
                if HomeworkSubNewComment.objects.filter(homeworksubmission=homeworksubcomment.homeworksubmission, user=student).exists():
                    homeworksubnewcomment = HomeworkSubNewComment.objects.get(homeworksubmission=homeworksubcomment.homeworksubmission, user=student)
                    homeworksubnewcomment.is_seen = False
                    homeworksubnewcomment.save()
                else:
                    HomeworkSubNewComment.objects.create(
                        homeworksubmission=homeworksubcomment.homeworksubmission,
                        user=student,
                        is_seen=False
                    )
            except Exception as e:
                return Response({"error": str(e)}, status=500)


        serializer = HomeworkSubCommentSerializer(homeworksubcomment, context={'user': request.user})

        return Response(serializer.data, status=status.HTTP_201_CREATED)

    def delete(self, request):
        data = json.loads(request.body)
        comment_id = data['id']

        try:
            comment = HomeworkSubComment.objects.get(id=comment_id)
            if comment.comment_by == request.user:
                comment.delete()

                return Response(status=status.HTTP_202_ACCEPTED)
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
        except HomeworkSubComment.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)


# class StorageUsage(APIView):
#     permission_classes = [IsAuthenticated]

#     def get(self, request, **kwargs):
#         course_id = kwargs['course_id']

#         if not request.user.is_anonymous:
#             if request.user.userinformation.role in ['Admin', 'AdminInstructor', 'Instructor']:
#                 # Calculate video files size and video length
#                 videos = Video.objects.filter(coursecontent__course_id=course_id)
#                 video_files_size = 0
#                 videos_duration = 0
#                 for video in videos:
#                     try:
#                         video_files_size += video.file.size
#                         videos_duration += int(VideoFileClip(video.file.path).duration)
#                     except:
#                         pass

#                 # Lecturenote files size
#                 lecture_notes = LectureNote.objects.filter(coursecontent__course_id=course_id)
#                 lecture_note_files_size = 0
#                 for lecture_note in lecture_notes:
#                     try:
#                         lecture_note_files_size += lecture_note.file.size
#                     except:
#                         pass

#                 # Homework files size
#                 homeworks = Homework.objects.filter(coursecontent__course_id=course_id)
#                 homework_files_size = 0
#                 for homework in homeworks:
#                     try:
#                         homework_files_size += homework.file.size
#                     except:
#                         pass

#                 # Homework submission files size
#                 homework_submissions = HomeworkSubmission.objects.filter(coursecontent__course_id=course_id)
#                 homework_submission_files_size = 0
#                 for homework_submission in homework_submissions:
#                     try:
#                         homework_submission_files_size += homework_submission.file.size
#                     except:
#                         pass

#                 # Homework submission review files size
#                 homework_sub_reviews = HomeworkSubReview.objects.filter(coursecontent__course_id=course_id)
#                 homework_sub_review_files_size = 0
#                 for homework_sub_review in homework_sub_reviews:
#                     try:
#                         homework_sub_review_files_size += homework_sub_review.file.size
#                     except:
#                         pass

#                 # Image file
#                 try:
#                     image_file_size = Course.objects.get(id=course_id).image.size
#                 except:
#                     image_file_size = 0

#                 total_files_size = video_files_size + lecture_note_files_size + homework_files_size + \
#                                   homework_submission_files_size + homework_sub_review_files_size + image_file_size

#                 return Response({'videos_size': get_file_size(video_files_size),
#                                  'videos_duration': get_video_duration(videos_duration),
#                                  'lecture_notes_size': get_file_size(lecture_note_files_size),
#                                  'homeworks_size': get_file_size(homework_files_size),
#                                  'homework_submissions_size': get_file_size(homework_submission_files_size),
#                                  'homework_sub_reviews_size': get_file_size(homework_sub_review_files_size),
#                                  'image_size': get_file_size(image_file_size),
#                                  'total_files_size': get_file_size(total_files_size)})
#             else:
#                 return Response(status=status.HTTP_401_UNAUTHORIZED)
#         return Response(status=status.HTTP_401_UNAUTHORIZED)


class UserCourseList(APIView):
    permission_classes = [IsAuthenticated]

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

        if user_information.role == 'Admin':
            course_id = request.GET.get('course_id', '')

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

            course_id = int(course_id)

            section_list = UserCourse.objects.filter(course=course_id, approval_status='Approved').order_by('-id')
            serializer = UserCourseSerializerAdmin(section_list, many=True)
            
            return Response({'section_list': serializer.data}, status=status.HTTP_200_OK)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)


class BookConsultationView(APIView):
    permission_classes = []

    def post(self, request, **kwargs):
        serializer = ConsultationSerializer(data=request.data)
        print(serializer)
        if serializer.is_valid():
            serializer.save()
            return Response({'success': 'Your consultation has been successfully booked! We will reach out to you soon.'}, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    def get(self, request, **kwargs):
        if request.user.userinformation.role == 'Admin':
            consultations = Consultation.objects.all()
            serializer = ConsultationSerializer(consultations, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)
        else:
            return Response({'error': 'Unauthorized'}, status=status.HTTP_401_UNAUTHORIZED)
        
