from django.shortcuts import render
from rest_framework import response
from rest_framework.schemas import inspectors
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from core.models import UserInformation, Instructor, InstructorTime, Course, InstructorHoldWeek, InstructorDocuments, InstructorEducation
from django.contrib.auth.models import User
from django.db.models import Q, Value
from django.db.models.functions import Concat
from django.core.mail import send_mail
from rest_framework.permissions import IsAuthenticated
from courses.serializers import CourseSerializer
from . serializers import (InstructorShortListSerializer, InstructorTimeSerializer, InstructorHoldWeekSerializer, InstructorDocumentsSerializer, InstructorDocumentsPostSerializer, 
                        InstructorShortUnauthListSerializer, InstructorDetailsUnauthListSerializer, InstructorEducationSerializer,
                        InstructorDetailsSerializer)
import json
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from core.permissions import IsAdmin, IsOrgAdmin, IsInstructor, IsStudent, IsGuardian
from datetime import datetime
from django.db import IntegrityError
from rest_framework.exceptions import ValidationError


# Create your views here.
class InstructorList(APIView):
    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin]

    def get(self, request):
        filter_item = request.GET.get('filter_item', '')
        data = []
        user_data = {}

        if filter_item:
            is_organization_options = [True]
        else:
            is_organization_options = [True, False]

        user = self.request.user
        user_information = UserInformation.objects.get(user=user.id)

        if user_information:
            if user_information.role in ['Admin', 'OrgAdmin']:
                search = request.GET.get('search', '')
                
                if user_information.role == 'OrgAdmin':
                    instructors = Instructor.objects.filter(
                        Q(user__userapproval__approval_status='Approved') &
                        Q(user__userinformation__organization=user_information.organization.id) & (
                        Q(name__trigram_word_similar=search) |
                        Q(name__icontains=search) |
                        Q(contact_email__icontains=search))
                    ).order_by('-id')    
                else:
                    instructors = Instructor.objects.filter(
                        Q(user__userapproval__approval_status='Approved') &
                        Q(user__userinformation__is_organization__in=is_organization_options) & (
                        Q(name__trigram_word_similar=search) |
                        Q(name__icontains=search) |
                        Q(contact_email__icontains=search))
                    ).order_by('-id')    
                
                for instructor in instructors:
                    data.append({
                        'id': instructor.id,
                        'name': f'{instructor.user.first_name} {instructor.user.last_name}',
                        'details': instructor.details,
                        'contact_email': instructor.contact_email,
                        'is_organization': instructor.user.userinformation.is_organization
                    })

                user_data = {'user_data': data}
                response_status = status.HTTP_200_OK
            else:
                response_status = status.HTTP_401_UNAUTHORIZED
        else:
            response_status = status.HTTP_404_NOT_FOUND

        return Response(user_data, status=response_status)

    # def post(self, request):
    #     name = request.data.get('name', None)
    #     contact_email = request.data.get('contact_email', None)
    #     occupation = request.data.get('occupation', None)
    #     details = request.data.get('details', None)
    #     data = []
    #     user_data = {}
    #     count = 0
    #     error = ''
    #     response_status = ''

    #     if not self.request.user.is_anonymous:
    #         if self.request.user.userinformation.role == 'Admin' or self.request.user.userinformation.role == 'AdminInstructor':
    #             email_exists = Instructor.objects.filter(contact_email=contact_email).exists()
    #             if email_exists==False:
    #                 if contact_email and name and occupation:
    #                     Instructor.objects.create(
    #                         name=name,
    #                         contact_email=contact_email,
    #                         occupation=occupation,
    #                         details=details
    #                     )
    #                     response_status = status.HTTP_201_CREATED

    #                     return Response({'success': 'Instructor Created. Waiting for instructor to singup.'}, status=response_status)
    #                 else:
    #                     error = 'Name, Contact or occupation email cannot be empty.'
    #                     response_status = status.HTTP_400_BAD_REQUEST
    #             else:
    #                 error = 'An instructor with this email already exists.'
    #                 response_status = status.HTTP_400_BAD_REQUEST
    #         else:
    #             error = 'Unauthorized access.'
    #             response_status = status.HTTP_401_UNAUTHORIZED
    #     else:
    #         error = 'Not Found.'
    #         response_status=status.HTTP_404_NOT_FOUND

    #     return Response({'error': error}, status=response_status)


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

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

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

        user = request.user
        user_information = user.userinformation

        if user_information.role == 'Instructor':
            instructor_id = user.instructor.id

        try:
            instructor = Instructor.objects.get(id=instructor_id)
        except Instructor.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role=='OrgAdmin':
            if user_information.organization.id != instructor.user.userinformation.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        if user_information.role=='Instructor':
            if instructor_id != user.instructor.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        
        serializer = InstructorDetailsSerializer(instructor)

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

    
    def delete(self, request):
        user = self.request.user
        user_information = UserInformation.objects.get(user=user.id)
        instructor_id = request.data.get('instructor_id', 0)

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

        counter = 0
        error = 'No Error'
        
        if user_information:
            if user_information.role in ['Admin', 'OrgAdmin']:
                if instructor_id:
                    try:
                        instructor = Instructor.objects.get(id=instructor_id)
                    except Instructor.DoesNotExist:
                        return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)
                    
                    if user_information.role == 'OrgAdmin':
                        if instructor.user.userinformation.is_organization:
                            if instructor.user.userinformation.organization.id != user_information.organization.id:
                                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
                        else:
                            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access'}, status=status.HTTP_401_UNAUTHORIZED)


                    if User.objects.filter(instructor=instructor).exists():
                        user_id = instructor.user.id
                        # Delete related user if exists
                        if user_id:
                            user = User.objects.get(id=user_id)
                            user.delete()   
                    instructor.delete()

                    return Response({'status': True, 'data': None, 'msg': 'Instructor deleted.'}, status=status.HTTP_200_OK)
                else:
                    error = 'Please select an instructor'
                    response_status = status.HTTP_400_BAD_REQUEST
            else:
                error = 'Unauthorized Access.'
                response_status = status.HTTP_401_UNAUTHORIZED
        else:
            error = 'Cannot find admin user.'
            response_status = status.HTTP_404_NOT_FOUND
        return Response({'status': False, 'data': None, 'msg': error}, status=response_status)
        
    
    def put(self, request):
        data = request.data
        user = self.request.user
        instructor_id = request.data.get('instructor_id', 0)

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

        if not user.is_anonymous:
            user_information = user.userinformation
            role = user_information.role

            if role == 'Instructor':
                instructor_id = user.instructor.id

            if role in ['Admin', 'OrgAdmin', 'Instructor']:
                try:
                    instructor = Instructor.objects.get(id=instructor_id)    
                except Instructor.DoesNotExist:
                    return Response({'status': False, 'data': None, "msg": "Instructor not found."}, status=status.HTTP_404_NOT_FOUND)
                
                if role == 'OrgAdmin':
                    if instructor.user.userinformation.is_organization:
                        if instructor.user.userinformation.organization.id != user_information.organization.id:
                            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access'}, status=status.HTTP_401_UNAUTHORIZED)
                    else:
                        return Response({'status': False, 'data': None, 'msg': 'Unauthorized access'}, status=status.HTTP_401_UNAUTHORIZED) 
                
                contact_email = data.get('contact_email', None)
                if contact_email:
                    existing_instructor = Instructor.objects.filter(Q(contact_email=contact_email) & ~Q(id=instructor_id)).exists()
                    if existing_instructor:
                        return Response({'status': False, 'data': None, 'msg': 'An instructor with this email already exists.'}, status=status.HTTP_400_BAD_REQUEST)

                # Update instructor details
                # instructor.user.first_name = data.get('first_name')
                # instructor.user.last_name = data.get('last_name')

                instructor.contact_email = data.get('contact_email', instructor.contact_email)
                instructor.user.email = data.get('contact_email', instructor.contact_email)
                instructor.user.save()

                is_organization = instructor.user.userinformation.is_organization
                instructor.user.userinformation.is_organization = data.get('is_organization', is_organization)
                instructor.user.userinformation.save()

                # instructor.name = f"{data.get('first_name')} {data.get('last_name')}"
                instructor.is_one_to_one = data.get('is_one_to_one', instructor.is_one_to_one)
                instructor.is_one_to_group = data.get('is_one_to_group', instructor.is_one_to_group)
                instructor.is_one_to_many = data.get('is_one_to_many', instructor.is_one_to_many)
                instructor.is_selfpaced = data.get('is_selfpaced', instructor.is_selfpaced)
                instructor.hourly_fee = data.get('hourly_fee', instructor.hourly_fee)
                instructor.city = data.get('city', instructor.city)
                instructor.language = data.get('language', instructor.language)
                instructor.details = data.get('details', instructor.details)
                instructor.wp_number = data.get('wp_number', instructor.wp_number)
                instructor.skype_id = data.get('skype_id', instructor.skype_id)
                instructor.website = data.get('website', instructor.website)
                instructor.linked_in_id = data.get('linked_in_id', instructor.linked_in_id)
                
                instructor.save()

                serializer = InstructorDetailsSerializer(instructor)

                return Response({'status': True, 'data': serializer.data, "msg": "Instructor details updated successfully!"}, status=status.HTTP_200_OK)
            else:
                error = 'Unauthorized access.'
                response_status = status.HTTP_401_UNAUTHORIZED
        else:
            error = 'Not Found.'
            response_status=status.HTTP_404_NOT_FOUND

        return Response({'status': False, 'data': None, 'msg': 'Unauthorized access'}, status=status.HTTP_401_UNAUTHORIZED)

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

    def put(self, request):
        email = request.data.get('email', None)
        organization_id = request.data.get('organization_id', 0)

        try:
            organization_id = int(organization_id)
        except:
            return Response({'error': 'Invalid organization id.'}, status=status.HTTP_400_BAD_REQUEST)

        user_information = request.user.userinformation

        if not email:
            return Response({'error': 'Please enter email.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            instructor = Instructor.object.get(contact_email=email)
        except Instructor.DoesNotExist:
            return Response({'error': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)

        if instructor.userinformation.is_organization:
            return Response({'error': 'Instructor is not registered as an organization instructor.'}, status=status.HTTP_400_BAD_REQUEST)

        # if instructor.userinformation.organization:
        #     return Response({'error': 'Instructor already assigned to an organization.'}, status=status.HTTP_400_BAD_REQUEST)

        user_approval = UserApproval.objects.get(user=instructor.user)

        if user_information.role == 'OrgAdmin':
            user_approval.approval_status = 'Approved'
            user_approval.save()

            instructor.user.userinformation.organization = user_information.organization
            instructor.user.userinformation.save()
        else:
            if not organization_id:
                return Response({'error': 'Please enter organization id.'}, status=status.HTTP_400_BAD_REQUEST)

            if user_approval.status != 'Approved':
                return Response({'error': 'Instructor is not approved.'}, status=status.HTTP_400_BAD_REQUEST)
            
            instructor.user.userinformation.organization = organization_id
            instructor.user.userinformation.save()

            return Response({'success': 'Instructor assigned to organization.'}, status=status.HTTP_200_OK)


class InstructorShortList(APIView):
    permission_classes = [IsAuthenticated]

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

        try:
            user_information = UserInformation.objects.get(user=user)
        except UserInformation.DoesNotExist:
            return Response({'error': 'Cannot find user'}, status=status.HTTP_404_NOT_FOUND)

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

        if course_id != '':
            instructors = Instructor.objects.filter(course__id=course_id, status='Active')
            serializer = InstructorShortListSerializer(instructors, many=True)
            
            return Response({'instructor_data': serializer.data}, status=status.HTTP_200_OK)
        else:
            instructor = Instructor.objects.filter(status='Active')
            serializer = InstructorShortListSerializer(instructor, many=True)

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




class InstructorShortUnauthList(APIView):
    permission_classes = []
    def get(self, request):

        instructor = Instructor.objects.filter(status='Active')
        serializer = InstructorShortUnauthListSerializer(instructor, many=True)

        return Response({'instructor_data': serializer.data, 'error': 'No Error'}, status=status.HTTP_200_OK)

class InstructorDetailsUnauthList(APIView):
    permission_classes = []
    def get(self, request):
        
        
        instructor = request.GET.get('instructor_id')
        instructor = Instructor.objects.filter(status='Active', id=instructor)
        serializer = InstructorDetailsUnauthListSerializer(instructor, many=True)

        return Response({'instructor_data': serializer.data, 'error': 'No Error'}, status=status.HTTP_200_OK)


class InstructorTimeList(APIView):
    permission_classes = [IsAuthenticated]

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

        try:
            if request.user.userinformation.role in ['Admin', 'OrgAdmin']:
                instructor_id = int(request.GET.get('instructor_id', None))
            elif request.user.userinformation.role == 'Instructor':
                instructor_id = int(request.user.instructor.id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        
        try:
            instructor = Instructor.objects.get(id=instructor_id)
        except Instructor.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Instructor Not found.'}, status=status.HTTP_400_BAD_REQUEST)
            
        if user_information.role=='Admin':
            instructor_time = InstructorTime.objects.filter(instructor=instructor_id)

            serializer = InstructorTimeSerializer(instructor_time, many=True)

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

        elif user_information.role=='Instructor':
            instructor = user.instructor
            instructor_time = InstructorTime.objects.filter(instructor=instructor)

            serializer = InstructorTimeSerializer(instructor_time, many=True)
            
            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor time list fetched.'}, status=status.HTTP_200_OK)
        else:
            return Response({'error': 'Unauthorized Access'}, status=status.HTTP_401_UNAUTHORIZED)


    def post(self, request):
        user = request.user
        user_information = user.userinformation
        day = request.data.get('day', '')
        time = request.data.get('time', None)
        booked_status = request.data.get('booked_status', False)

        try:
            if request.user.userinformation.role in ['Admin', 'OrgAdmin']:
                instructor_id = int(request.GET.get('instructor_id', None))
            elif request.user.userinformation.role == 'Instructor':
                instructor_id = int(request.user.instructor.id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        day = request.data.get('day', None)

        if day not in ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Friday', 'Saturday']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid day.'}, status=status.HTTP_400_BAD_REQUEST)

        if not time:
            return Response({'status': False, 'data': None, 'msg': 'Please enter a time.'}, status=status.HTTP_400_BAD_REQUEST)
            
        try:
            instructor = Instructor.objects.get(id=instructor_id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)
        
        if user_information.role=='Instructor':
            instructor = user.instructor
        elif user_information.role=='OrgAdmin':
            if not instructor.user.user_information.is_organization:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                if instructor.user.user_information.oranization != user.userinformation.oranization:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        
        
        instructor_time = InstructorTime.objects.create(instructor = instructor, day = day, time = time, booked_status = booked_status)
        serializer = InstructorTimeSerializer(instructor_time)
        

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



    def put(self, request):
        user = request.user
        day = request.data.get('day', '')
        time = request.data.get('time', '')
        booked_status = request.data.get('booked_status', False)
        user_information = user.userinformation

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

        try:
            instructor_time = InstructorTime.objects.get(id=instructor_time_id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor time not found.'}, status=status.HTTP_404_NOT_FOUND)

        if day not in ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Friday', 'Saturday']:
            return Response({'status': False, 'data': None, 'msg': 'Invalid day.'}, status=status.HTTP_400_BAD_REQUEST)

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

        if user_information.role=='Admin':
            instructor_time.day = day
            instructor_time.day = time
            instructor_time.booked_status = booked_status

            instructor_time.save()
            serializer = InstructorTimeSerializer(instructor_time)

            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor time updated.'}, status.HTTP_200_OK)
        elif user_information.role=='Instructor':
            if instructor_time.instructor != user.instructor:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)             
            
            instructor_time.day = day
            instructor_time.time = time
            instructor_time.booked_status = booked_status

            instructor_time.save()
            serializer = InstructorTimeSerializer(instructor_time)

            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor time updated.'}, status.HTTP_200_OK)
        elif user_information.role=='OrgAdmin':
            if not instructor_time.instructor.user.user_information.is_organization:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                if instructor_time.instructor.user.user_information.oranization != user.userinformation.oranization:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            

            instructor_time.day = day
            instructor_time.time = time
            instructor_time.booked_status = booked_status

            instructor_time.save()
            serializer = InstructorTimeSerializer(instructor_time)

            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor time updated.'}, status.HTTP_200_OK)
        else:
            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)



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


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

        try:
            instructor_time = InstructorTime.objects.get(id=instructor_time_id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor time not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_information.role=='Admin':
            instructor_time.delete()

            return Response({'status': True, 'data': None, 'msg': 'Instructor time deleted.'}, status.HTTP_200_OK)
        elif user_information.role=='Instructor':
            if instructor_time.instructor != user.instructor:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)             
            
            instructor_time.delete()

            return Response({'status': True, 'data': None, 'msg': 'Instructor time deleted.'}, status.HTTP_200_OK)
        elif user_information.role=='OrgAdmin':
            if not instructor_time.instructor.user.user_information.is_organization:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            else:
                if instructor_time.instructor.user.user_information.oranization != user.userinformation.oranization:
                    return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            

            instructor_time.delete()

            return Response({'status': True, 'data': None, 'msg': 'Instructor time deleted.'}, status.HTTP_200_OK)
        else:
            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
            
            

class InstructorHoldWeekManage(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = self.request.user
        instructor_id = request.GET.get('instructor_id')
        # print(user)
        if not user.is_anonymous:
            if user.userinformation.role in ['Admin', 'AdminInstructor']:
                instructor = Instructor.objects.get(id=instructor_id)
                instruct_name = instructor.name
                courses_queryset = Course.objects.filter(instructor=instructor).order_by('-academic_session')

                courses = []
                for course in courses_queryset:
                    course_dict =  {}
                    course_dict['id'] = course.id
                    course_dict['title'] = course.title
                    course_dict['academicsession'] = course.academic_session.title
                    if InstructorHoldWeek.objects.filter(course=course, instructor=instructor).exists():
                        hold_weeks = InstructorHoldWeek.objects.filter(course=course, instructor=instructor)
                        serializer = InstructorHoldWeekSerializer(hold_weeks, many=True)
                        course_dict['hold_week'] = serializer.data
                    else:
                        course_dict['hold_week'] = []
                    courses.append(course_dict)

                return Response({'name': instruct_name, 'courses': courses}, status=status.HTTP_200_OK)
            else:
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

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

        if not user.is_anonymous:
            if user.userinformation.role in ['Admin', 'AdminInstructor']:
                instructor = Instructor.objects.get(id=instructor_id)
                InstructorHoldWeek.objects.create(
                    instructor=Instructor.objects.get(id=instructor_id),
                    course=Course.objects.get(id=course_id),
                    week=week
                )

                courses_queryset = Course.objects.filter(instructor=instructor_id).order_by('-academic_session')
                courses = []
                for course in courses_queryset:
                    course_dict =  {}
                    course_dict['id'] = course.id
                    course_dict['title'] = course.title
                    course_dict['academicsession'] = course.academic_session.title
                    if InstructorHoldWeek.objects.filter(course=course, instructor=instructor).exists():
                        hold_week = InstructorHoldWeek.objects.filter(course=course, instructor=instructor)
                        serializer = InstructorHoldWeekSerializer(hold_week, many=True)
                        course_dict['hold_week'] = serializer.data
                    else:
                        course_dict['hold_week'] = []
                    courses.append(course_dict)

                return Response({'courses': courses}, status=status.HTTP_201_CREATED)
            else:
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)

    def delete(self, request):
        user = self.request.user
        instructor_id = request.data['instructor_id']
        hold_week_id = request.data['hold_week_id']

        if not user.is_anonymous:
            if user.userinformation.role in ['Admin', 'AdminInstructor']:
                instructor = Instructor.objects.get(id=instructor_id)
                InstructorHoldWeek.objects.filter(id=hold_week_id).delete()

                courses_queryset = Course.objects.filter(instructor=instructor_id).order_by('-academic_session')
                courses = []
                for course in courses_queryset:
                    course_dict =  {}
                    course_dict['id'] = course.id
                    course_dict['title'] = course.title
                    course_dict['academicsession'] = course.academic_session.title
                    if InstructorHoldWeek.objects.filter(course=course, instructor=instructor).exists():
                        hold_week = InstructorHoldWeek.objects.filter(course=course, instructor=instructor)
                        serializer = InstructorHoldWeekSerializer(hold_week, many=True)
                        course_dict['hold_week'] = serializer.data
                    else:
                        course_dict['hold_week'] = []
                    courses.append(course_dict)

                return Response({'course': courses}, status=status.HTTP_202_ACCEPTED)
            else:
                return Response(status=status.HTTP_403_FORBIDDEN)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)


class InstructorDocumentView(APIView):

    permission_classes = [IsAuthenticated, IsAdmin | IsOrgAdmin | IsInstructor]

    def get(self, request):
        
        try:
            if request.user.userinformation.role in ['Admin', 'OrgAdmin']:
                instructor_id = int(request.GET.get('instructor_id', None))
            elif request.user.userinformation.role == 'Instructor':
                instructor_id = int(request.user.instructor.id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)
        
        user = request.user
        user_role = user.userinformation.role
        
        try:
            instructor = Instructor.objects.get(id=instructor_id)
        except Instructor.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)

        if user_role=='Instructor':
            if instructor_id != user.instructor.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        documents = InstructorDocuments.objects.filter(instructor=instructor)

        # Serialize the list of documents and return
        serializer = InstructorDocumentsSerializer(documents, many=True)
        return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor document list fetched.'}, status=status.HTTP_200_OK)


    def post(self, request):
        try:
            if request.user.userinformation.role in ['Admin', 'OrgAdmin']:
                instructor_id = int(request.GET.get('instructor_id', None))
            elif request.user.userinformation.role == 'Instructor':
                instructor_id = int(request.user.instructor.id)
        except:
            return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            instructor = Instructor.objects.get(id=instructor_id)
        except Instructor.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_400_BAD_REQUEST)

        user = request.user
        user_role = user.userinformation.role

        if user_role == 'Instructor':
            if instructor_id != user.instructor.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        title = request.data.get('title', '')
        file = request.FILES.get('file', None)
        source_type = request.data.get('source_type', None)
        # thumbnail = request.data.get('thumbnail', None)

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

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

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

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

        document_data = {
            'title': title,
            'instructor': instructor.id,
            'source_type': source_type,
            'file': file,
        }

        serializer = InstructorDocumentsPostSerializer(data=document_data)
        if serializer.is_valid():
            serializer.save()

            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor document created'}, status=status.HTTP_201_CREATED)
        else:
            msg = []
            errors = serializer.errors
            for key, value in errors.items():
                if key=='non_field_errors':
                    key='error'
                key = key.replace('_', ' ').capitalize()
                for i in value:
                    msg.append(key+': '+i)

            return Response({'status': False, 'data': None, 'msg': msg}, status=status.HTTP_400_BAD_REQUEST)



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

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

        if len(title)>128:
            return Response({'status': False, 'data': None, 'msg': 'Title must be less than or equal to 128 characters.'}, status=status.HTTP_400_BAD_REQUEST)

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

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

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

        user = request.user
        user_role = user.userinformation.role
        
        try:
            document = InstructorDocuments.objects.get(id=instructor_document_id)
        except InstructorDocuments.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Instructor document not found.'}, status=status.HTTP_404_NOT_FOUND)

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

        # If Instructor, check ownership
        if user_role == 'Instructor' and document.instructor.id != user.instructor.id:
            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        if file:
            document.file = file
        
        document.title = title
        document.source_type = source_type
        document.save()

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


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

        user_role = request.user.userinformation.role

        try:
            document = InstructorDocuments.objects.get(id=document_id)
        except InstructorDocuments.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Document not found.'})

        # If Instructor, check ownership
        if user_role == 'Instructor' and document.instructor.id != request.user.id:
            return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)

        document.delete()
        return Response({'status': True, 'data': None, 'msg': 'Document deleted successfully.'}, status=status.HTTP_200_OK)



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

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

        if user_information.role == 'Instructor':
            instructor_id = user.instructor.id
        elif user_information.role == 'OrgAdmin':
            try:
                instructor_id = int(request.GET.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

            try:
                instructor = Instructor.objects.get(id=instructor_id)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)

            if instructor.user.userinformation.is_organization is False or instructor.user.userinformation.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            try:
                instructor_id = int(request.GET.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': serializer.data, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        educations = InstructorEducation.objects.filter(instructor=instructor_id)
        
        serialized = []
        for index, edu in enumerate(educations, start=1):
            serializer = InstructorEducationSerializer(edu, context={'education_completion': index})
            serialized.append(serializer.data)

        return Response({'status': True, 'data': serialized, 'msg': 'Instructor education list fetched.'}, status=status.HTTP_200_OK)

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

        if user_information.role=='Instructor':
            instructor_id = user.instructor.id

            # if user.user_information.status != 'Approved':
            #     return Response({'status': False, 'data': None, 'msg': 'Instructor not approved.'}, status=status.HTTP_400_BAD_REQUEST)
        elif user_information.role == 'OrgAdmin':
            try:
                instructor_id = int(request.GET.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

            try:
                instructor = Instructor.objects.get(id=instructor_id)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)

            if instructor.user.userinformation.is_organization is False or instructor.user.userinformation.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            try:
                instructor_id = int(request.data.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

        
        degree = request.data.get('degree', '')
        university_name = request.data.get('university_name', '')
        university_city = request.data.get('university_city', '')
        university_country = request.data.get('university_country', '')
        session_start = request.data.get('session_start', '')
        session_end = request.data.get('session_end', '')
        degree_details = request.data.get('degree_details', '')

        data = {
            'instructor': instructor_id,
            'degree': degree,
            'university_name': university_name,
            'university_city': university_city,
            'university_country': university_country,
            'session_start': session_start,
            'session_end': session_end,
            'degree_details': degree_details,
        }

        serializer = InstructorEducationSerializer(data=data)

        if serializer.is_valid():
            serializer.save()

            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor education created.'}, status=status.HTTP_201_CREATED)
        else:
            msg = []
            errors = serializer.errors
            for key, value in errors.items():
                if key=='non_field_errors':
                    key='error'
                key = key.replace('_', ' ').capitalize()
                for i in value:
                    msg.append(key+': '+i)

            return Response({'status': False, 'data': None, 'msg': msg}, status=status.HTTP_400_BAD_REQUEST)


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

    def get_object(self, instructor, education_id):
        """Retrieve a specific education entry for the instructor."""
        try:
            return InstructorEducation.objects.get(instructor=instructor, id=education_id)
        except InstructorEducation.DoesNotExist:
            return None

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

        user = request.user
        user_information = user.userinformation
        
        if user_information.role=='Instructor':
            instructor_id = user.instructor.id

            if user.instructor.status != 'Approved':
                return Response({'status': False, 'data': None, 'msg': 'Instructor not approved.'}, status=status.HTTP_400_BAD_REQUEST)
        elif user_information.role == 'OrgAdmin':
            try:
                instructor_id = int(request.GET.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

            try:
                instructor = Instructor.objects.get(id=instructor_id)
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)

            if instructor.user.userinformation.is_organization is False or instructor.user.userinformation.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            try:
                instructor_id = int(request.GET.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)


        try:
            education = InstructorEducation.objects.get(id=education_id, instructor=instructor_id)
        except InstructorEducation.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Education object not found.'}, status=status.HTTP_404_NOT_FOUND)


        serializer = InstructorEducationSerializer(education)

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


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

        user = request.user
        user_information = user.userinformation
        
        if user_information.role=='Instructor':
            instructor_id = user.instructor.id

            # if user.instructor.status != 'Approved':
            #     return Response({'status': False, 'data': None, 'msg': 'Instructor not approved.'}, status=status.HTTP_400_BAD_REQUEST)
        elif user_information.role == 'OrgAdmin':
            try:
                instructor_id = int(request.data.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

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

            if instructor.user.userinformation.is_organization is False or instructor.user.userinformation.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            try:
                instructor_id = int(request.data.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)


        try:
            education = InstructorEducation.objects.get(id=education_id, instructor=instructor_id)
        except InstructorEducation.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Education object not found.'}, status=status.HTTP_404_NOT_FOUND)

        request.data['id'] = education_id
        request.data['instructor'] = instructor_id

        serializer = InstructorEducationSerializer(education, data=request.data)

        if serializer.is_valid():
            serializer.save()
            return Response({'status': True, 'data': serializer.data, 'msg': 'Instructor education updated.'}, status=status.HTTP_200_OK)
        else:
            msg = []
            errors = serializer.errors
            for key, value in errors.items():
                if key=='non_field_errors':
                    key='error'
                key = key.replace('_', ' ').capitalize()
                for i in value:
                    msg.append(key+': '+i)

            return Response({'status': False, 'data': None, 'msg': msg}, status=status.HTTP_400_BAD_REQUEST)

        

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

        user = request.user
        user_information = user.userinformation
        
        if user_information.role=='Instructor':
            instructor_id = user.instructor.id

            # if user.instructor.status != 'Approved':
            #     return Response({'status': False, 'data': None, 'msg': 'Instructor not approved.'}, status=status.HTTP_400_BAD_REQUEST)
        elif user_information.role == 'OrgAdmin':
            try:
                instructor_id = int(request.data.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)

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

            if instructor.user.userinformation.is_organization is False or instructor.user.userinformation.organization.id != user_information.organization.id:
                return Response({'status': False, 'data': None, 'msg': 'Unauthorized access.'}, status=status.HTTP_401_UNAUTHORIZED)
        else:
            try:
                instructor_id = int(request.data.get('instructor_id', None))
            except:
                return Response({'status': False, 'data': None, 'msg': 'Instructor id must be an integer.'}, status=status.HTTP_400_BAD_REQUEST)


        try:
            education = InstructorEducation.objects.get(id=education_id, instructor=instructor_id)
        except InstructorEducation.DoesNotExist:
            return Response({'status': False, 'data': None, 'msg': 'Education object not found.'}, status=status.HTTP_404_NOT_FOUND)

        education.delete()

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


class InstructorProfileCompletion(APIView):
    permission_classes = [IsAuthenticated, IsInstructor]

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

        try:
            instructor = Instructor.objects.get(user=user)
        except Instructor.DoesNotExist:
            return Response({'status': False, 'msg': 'Instructor not found'}, status=status.HTTP_404_NOT_FOUND)

        educations = InstructorEducation.objects.filter(instructor=request.user.instructor.id)
        
        serialized = []

        if educations.exists():
            for index, edu in enumerate(educations, start=1):
                serializer = InstructorEducationSerializer(edu, context={'education_completion': index})
                serialized.append(serializer.data)
        else:
            # Return a default completion value if there are no educations
            serialized.append({'education_completion': 0})

        completion = {
            'user_completion': user_information.calculate_user_profile_completion(),
            'instructor_completion': instructor.calculate_instructor_profile_completion(),
            'education_completion': serialized[-1].get('education_completion', 0), 
            'profile_status': user_information.profile_lock,
        }

        return Response({'status': True, 'data': completion, 'msg': 'Profile completion fetched.'}, status=status.HTTP_200_OK)
    
    def put(self, request):
        user = request.user
        user_information = user.userinformation

        user_information.profile_lock = "waiting_approval"
        user_information.save()
               

        return Response({'status': True, 'data': '', 'msg': 'Submited for Admin Review.'}, status=status.HTTP_200_OK)

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

    def get(self, request):
        try:
            data = []
            profilereviews = UserInformation.objects.filter(
                profile_lock="waiting_approval",
                role="Instructor"
            )

            for user_profile in profilereviews:
                user = user_profile.user
                data.append({
                    'request_id': user.instructor.id,
                    'username': user.username,
                    'request_name': f'{user.first_name} {user.last_name}',
                    'contact_email': user.email,
                    'role': user_profile.role,
                    'is_organization': user_profile.is_organization,
                    'approval_status': user_profile.profile_lock,
                })

        except Exception as e:
            return Response({'status': False, 'msg': f'Error occurred: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        return Response({'status': True, 'data': data, 'msg': 'Profile completion fetched.'}, status=status.HTTP_200_OK)
    
    def put(self, request):
        try:
            request_id = request.data.get("request_id")
            new_status = request.data.get("status")
            note = request.data.get("note", "")

            if not request_id or not new_status:
                return Response({'status': False, 'msg': 'Missing required fields.'}, status=status.HTTP_400_BAD_REQUEST)

            instructor = Instructor.objects.get(id=request_id)
            user_info = instructor.user.userinformation

            user_info.profile_lock = new_status
            user_info.save()

            # Optionally, save the note somewhere, e.g. in a log model or print/log
            print(f"Admin note: {note}")  # or store in DB if needed

            return Response({'status': True, 'msg': 'Profile status updated successfully.'}, status=status.HTTP_200_OK)

        except Instructor.DoesNotExist:
            return Response({'status': False, 'msg': 'Instructor not found.'}, status=status.HTTP_404_NOT_FOUND)
        except Exception as e:
            return Response({'status': False, 'msg': f'Error: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

