from django.http.response import JsonResponse
from django.views.decorators.csrf import ensure_csrf_cookie, csrf_protect
from django.utils.decorators import method_decorator
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView
from rest_framework import status
from .models import (
    Teacher, 
    Speciality, 
    SchoolClass, 
    Planning, 
    Discount, 
    Fee, 
    PaymentPlan, 
    PaymentMode
)
from .serializers import (
    TeacherSerializer, 
    SpecialitySerializer, 
    SchoolClassSerializer, 
    PlanningSerializer, 
    DiscountSerializer, 
    FeeSerializer, 
    PaymentPlanSerializer, 
    PaymentModeSerializer
)
from N3wtSchool.bdd import delete_object, getAllObjects, getObject

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class SpecialityListCreateView(APIView):
    def get(self, request):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        specialities_list = getAllObjects(Speciality)
        if establishment_id:
            specialities_list = specialities_list.filter(establishment__id=establishment_id).distinct()
        specialities_serializer = SpecialitySerializer(specialities_list, many=True)
        return JsonResponse(specialities_serializer.data, safe=False)

    def post(self, request):
        speciality_data=JSONParser().parse(request)
        speciality_serializer = SpecialitySerializer(data=speciality_data)

        if speciality_serializer.is_valid():
            speciality_serializer.save()
            return JsonResponse(speciality_serializer.data, safe=False, status=status.HTTP_201_CREATED)

        return JsonResponse(speciality_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class SpecialityDetailView(APIView):
    def get(self, request, id):
        speciality = getObject(_objectName=Speciality, _columnName='id', _value=id)
        speciality_serializer=SpecialitySerializer(speciality)
        return JsonResponse(speciality_serializer.data, safe=False)

    def put(self, request, id):
        speciality_data=JSONParser().parse(request)
        speciality = getObject(_objectName=Speciality, _columnName='id', _value=id)
        speciality_serializer = SpecialitySerializer(speciality, data=speciality_data)
        if speciality_serializer.is_valid():
            speciality_serializer.save()
            return JsonResponse(speciality_serializer.data, safe=False)

        return JsonResponse(speciality_serializer.errors, safe=False)

    def delete(self, request, id):
        return delete_object(Speciality, id)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class TeacherListCreateView(APIView):
    def get(self, request):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        teachers_list = getAllObjects(Teacher)
        if teachers_list:
            teachers_list = teachers_list.filter(profile_role__establishment_id=establishment_id)
        teachers_serializer = TeacherSerializer(teachers_list, many=True)
        return JsonResponse(teachers_serializer.data, safe=False)

    def post(self, request):
        teacher_data=JSONParser().parse(request)
        teacher_serializer = TeacherSerializer(data=teacher_data)

        if teacher_serializer.is_valid():
            teacher_serializer.save()
            
            return JsonResponse(teacher_serializer.data, safe=False)           

        return JsonResponse(teacher_serializer.errors, safe=False)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class TeacherDetailView(APIView):
    def get (self, request, id):
        teacher = getObject(_objectName=Teacher, _columnName='id', _value=id)
        teacher_serializer=TeacherSerializer(teacher)

        return JsonResponse(teacher_serializer.data, safe=False)

    def put(self, request, id):
        teacher_data=JSONParser().parse(request)
        teacher = getObject(_objectName=Teacher, _columnName='id', _value=id)
        teacher_serializer = TeacherSerializer(teacher, data=teacher_data)
        if teacher_serializer.is_valid():
            teacher_serializer.save()
            return JsonResponse(teacher_serializer.data, safe=False)

        return JsonResponse(teacher_serializer.errors, safe=False)

    def delete(self, request, id):
        return delete_object(Teacher, id, related_field='profile')

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class SchoolClassListCreateView(APIView):
    def get(self, request):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        school_classes_list = getAllObjects(SchoolClass)
        if school_classes_list:
            school_classes_list = school_classes_list.filter(establishment=establishment_id).distinct()
        classes_serializer = SchoolClassSerializer(school_classes_list, many=True)
        return JsonResponse(classes_serializer.data, safe=False)

    def post(self, request):
        classe_data=JSONParser().parse(request)
        classe_serializer = SchoolClassSerializer(data=classe_data)

        if classe_serializer.is_valid():
            classe_serializer.save()            
            return JsonResponse(classe_serializer.data, safe=False)

        return JsonResponse(classe_serializer.errors, safe=False)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class SchoolClassDetailView(APIView):
    def get (self, request, id):
        schoolClass = getObject(_objectName=SchoolClass, _columnName='id', _value=id)
        classe_serializer=SchoolClassSerializer(schoolClass)

        return JsonResponse(classe_serializer.data, safe=False)

    def put(self, request, id):
        classe_data=JSONParser().parse(request)
        schoolClass = getObject(_objectName=SchoolClass, _columnName='id', _value=id)
        classe_serializer = SchoolClassSerializer(schoolClass, data=classe_data)
        if classe_serializer.is_valid():
            classe_serializer.save()
            return JsonResponse(classe_serializer.data, safe=False)

        return JsonResponse(classe_serializer.errors, safe=False)

    def delete(self, request, id):
        return delete_object(SchoolClass, id)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class PlanningListCreateView(APIView):
    def get(self, request):
        schedulesList=getAllObjects(Planning)
        schedules_serializer=PlanningSerializer(schedulesList, many=True)
        return JsonResponse(schedules_serializer.data, safe=False)

    def post(self, request):
        planning_data=JSONParser().parse(request)
        planning_serializer = PlanningSerializer(data=planning_data)

        if planning_serializer.is_valid():
            planning_serializer.save()
            return JsonResponse(planning_serializer.data, safe=False)

        return JsonResponse(planning_serializer.errors, safe=False)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class PlanningDetailView(APIView):
    def get (self, request, id):
        planning = getObject(_objectName=Planning, _columnName='classe_id', _value=id)
        planning_serializer=PlanningSerializer(planning)

        return JsonResponse(planning_serializer.data, safe=False)

    def put(self, request, id):
        planning_data = JSONParser().parse(request)
        
        try:
            planning = Planning.objects.get(id=id)
        except Planning.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)
        except Planning.MultipleObjectsReturned:
            return JsonResponse({'error': 'Multiple objects found'}, status=status.HTTP_400_BAD_REQUEST)

        planning_serializer = PlanningSerializer(planning, data=planning_data)

        if planning_serializer.is_valid():
            planning_serializer.save()
            return JsonResponse(planning_serializer.data, safe=False)

        return JsonResponse(planning_serializer.errors, safe=False)
    
    def delete(self, request, id):
        return delete_object(Planning, id)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class FeeListCreateView(APIView):
    def get(self, request, *args, **kwargs):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        filter = request.GET.get('filter', '').strip()
        fee_type_value = 0 if filter == 'registration' else 1

        fees = Fee.objects.filter(type=fee_type_value, establishment_id=establishment_id).distinct()
        fee_serializer = FeeSerializer(fees, many=True)
        
        return JsonResponse(fee_serializer.data, safe=False, status=status.HTTP_200_OK)

    def post(self, request):
        fee_data = JSONParser().parse(request)
        fee_serializer = FeeSerializer(data=fee_data)
        if fee_serializer.is_valid():
            fee_serializer.save()
            return JsonResponse(fee_serializer.data, safe=False, status=status.HTTP_201_CREATED)
        return JsonResponse(fee_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class FeeDetailView(APIView):
    def get(self, request, id):
        try:
            fee = Fee.objects.get(id=id)
            fee_serializer = FeeSerializer(fee)
            return JsonResponse(fee_serializer.data, safe=False)
        except Fee.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)

    def put(self, request, id):
        fee_data = JSONParser().parse(request)
        try:
            fee = Fee.objects.get(id=id)
        except Fee.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)
        fee_serializer = FeeSerializer(fee, data=fee_data, partial=True)
        if fee_serializer.is_valid():
            fee_serializer.save()
            return JsonResponse(fee_serializer.data, safe=False)
        return JsonResponse(fee_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, id):
        return delete_object(Fee, id)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class DiscountListCreateView(APIView):
    def get(self, request, *args, **kwargs):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        filter = request.GET.get('filter', '').strip()
        discount_type_value = 0 if filter == 'registration' else 1

        discounts = Discount.objects.filter(type=discount_type_value, establishment_id=establishment_id).distinct()
        discounts_serializer = DiscountSerializer(discounts, many=True)
        
        return JsonResponse(discounts_serializer.data, safe=False, status=status.HTTP_200_OK)

    def post(self, request):
        discount_data = JSONParser().parse(request)
        discount_serializer = DiscountSerializer(data=discount_data)
        if discount_serializer.is_valid():
            discount_serializer.save()
            return JsonResponse(discount_serializer.data, safe=False, status=status.HTTP_201_CREATED)
        return JsonResponse(discount_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class DiscountDetailView(APIView):
    def get(self, request, id):
        try:
            discount = Discount.objects.get(id=id)
            discount_serializer = DiscountSerializer(discount)
            return JsonResponse(discount_serializer.data, safe=False)
        except Discount.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)

    def put(self, request, id):
        discount_data = JSONParser().parse(request)
        try:
            discount = Discount.objects.get(id=id)
        except Discount.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)
        discount_serializer = DiscountSerializer(discount, data=discount_data, partial=True)  # Utilisation de partial=True
        if discount_serializer.is_valid():
            discount_serializer.save()
            return JsonResponse(discount_serializer.data, safe=False)
        return JsonResponse(discount_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, id):
        return delete_object(Discount, id)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class PaymentPlanListCreateView(APIView):
    def get(self, request, *args, **kwargs):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        filter = request.GET.get('filter', '').strip()
        type_value = 0 if filter == 'registration' else 1

        payment_plans = PaymentPlan.objects.filter(type=type_value, establishment_id=establishment_id).distinct()
        payment_plans_serializer = PaymentPlanSerializer(payment_plans, many=True)
        
        return JsonResponse(payment_plans_serializer.data, safe=False, status=status.HTTP_200_OK)

    def post(self, request):
        payment_plan_data = JSONParser().parse(request)
        payment_plan_serializer = PaymentPlanSerializer(data=payment_plan_data)
        if payment_plan_serializer.is_valid():
            payment_plan_serializer.save()
            return JsonResponse(payment_plan_serializer.data, safe=False, status=status.HTTP_201_CREATED)
        return JsonResponse(payment_plan_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class PaymentPlanDetailView(APIView):
    def get(self, request, id):
        try:
            payment_plan = PaymentPlan.objects.get(id=id)
            payment_plan_serializer = PaymentPlanSerializer(payment_plan)
            return JsonResponse(payment_plan_serializer.data, safe=False)
        except PaymentPlan.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)

    def put(self, request, id):
        payment_plan_data = JSONParser().parse(request)
        try:
            payment_plan = PaymentPlan.objects.get(id=id)
        except PaymentPlan.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)
        payment_plan_serializer = PaymentPlanSerializer(payment_plan, data=payment_plan_data, partial=True)
        if payment_plan_serializer.is_valid():
            payment_plan_serializer.save()
            return JsonResponse(payment_plan_serializer.data, safe=False)
        return JsonResponse(payment_plan_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, id):
        return delete_object(PaymentPlan, id)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class PaymentModeListCreateView(APIView):
    def get(self, request):
        establishment_id = request.GET.get('establishment_id', None)
        if establishment_id is None:
            return JsonResponse({'error': 'establishment_id est requis'}, safe=False, status=status.HTTP_400_BAD_REQUEST)

        filter = request.GET.get('filter', '').strip()
        type_value = 0 if filter == 'registration' else 1

        payment_modes = PaymentMode.objects.filter(type=type_value, establishment_id=establishment_id).distinct()
        payment_modes_serializer = PaymentModeSerializer(payment_modes, many=True)
        
        return JsonResponse(payment_modes_serializer.data, safe=False, status=status.HTTP_200_OK)

    def post(self, request):
        payment_mode_data = JSONParser().parse(request)
        payment_mode_serializer = PaymentModeSerializer(data=payment_mode_data)
        if payment_mode_serializer.is_valid():
            payment_mode_serializer.save()
            return JsonResponse(payment_mode_serializer.data, safe=False, status=status.HTTP_201_CREATED)
        return JsonResponse(payment_mode_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

@method_decorator(csrf_protect, name='dispatch')
@method_decorator(ensure_csrf_cookie, name='dispatch')
class PaymentModeDetailView(APIView):
    def get(self, request, id):
        try:
            payment_mode = PaymentMode.objects.get(id=id)
            payment_mode_serializer = PaymentModeSerializer(payment_mode)
            return JsonResponse(payment_mode_serializer.data, safe=False)
        except PaymentMode.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)

    def put(self, request, id):
        payment_mode_data = JSONParser().parse(request)
        try:
            payment_mode = PaymentMode.objects.get(id=id)
        except PaymentMode.DoesNotExist:
            return JsonResponse({'error': 'No object found'}, status=status.HTTP_404_NOT_FOUND)
        payment_mode_serializer = PaymentModeSerializer(payment_mode, data=payment_mode_data, partial=True)
        if payment_mode_serializer.is_valid():
            payment_mode_serializer.save()
            return JsonResponse(payment_mode_serializer.data, safe=False)
        return JsonResponse(payment_mode_serializer.errors, safe=False, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, id):
        return delete_object(PaymentMode, id)
