from django.shortcuts import render,redirect
from mainApp.models import *
from mainApp.serializers import *
from .models import *
from .serializers import *
from .utils import *
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
#from datetime import  timedelta
from django.utils import timezone
#from django.db.models import Q
from django.db.models import Max
# Create your views here.
from django.http import JsonResponse

############## GENERAL_TOOLS #################
def getClinicId(request):
    try :
        clinicId =  request.session['clinicId'] if 'clinicId' in request.session else request.user.groups.first().clinic.id
    except :
        clinicId = None
    return clinicId
############## END GENERAL_TOOLS #################

############## User%Module #################

@login_required(login_url='mainApp:login')
def welcome(request):
    user_clinic_image = Clinic.objects.get(id=request.session['clinicId']).welcome_img.url
    return render(request,'receptionApp/welcome.html',{"user_clinic_image":user_clinic_image})

############## END User%Module #################

############## Finance%Module #################
class ExpensesApi(APIView):
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_patients'), login_url='/main/login/'))
    # def get(self,request):
    #     if not getClinicId(request) : return redirect('/main/login/')
    #     all_patients =Patient.objects.all()
    #     all_patients_serialized=PatientSerializer(all_patients,many=True)
    #     return render(request,"mainApp/patientPages/patients.html",{"all_patients":all_patients_serialized.data,'activePage':'Patients'})

    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.add_patients'), login_url='/main/login/'))    
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        request.data._mutable = True
        request.data.update({"created_by":request.user.id})
        serializedObj= ExpenseSerializer(data=request.data)
        if serializedObj.is_valid():
            serializedObj.save()
            return Response(status=status.HTTP_201_CREATED)
        else :return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)

class MedServiceReportDoctor(APIView):
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        medical_services = MedicalService.objects.filter(is_service=True).values("id","name")
        doctors =User.objects.filter(is_doctor=True,is_active=True).values("id","first_name","last_name")
        return render(request,"receptionApp/financePages/med_service/recp_doctor.html",{
            "medical_services":medical_services,
            "doctors":doctors,
            'activePage':'MedServiceReportDoctor'})
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        data=request.data
        startDate = data["startDate"]
        startDateTime= datetime.strptime(startDate,"%Y-%m-%d")
        endDate = data["endDate"]
        endDateTime= datetime.strptime(endDate,"%Y-%m-%d").replace(hour=23,minute=59,second=59) 
        doctor = data["doctor"]
        medicalservice=data["medicalservice"]
        if medicalservice == "0" :
            visits = PatientVisit.objects.filter(created_at__gte = startDateTime , created_at__lte=endDateTime,doctor_id=doctor,visit_status="4F").order_by("created_at")
        else : 
            visits = PatientVisit.objects.filter(created_at__gte = startDateTime , created_at__lte=endDateTime,doctor_id=doctor,medicalservice_id=medicalservice,visit_status="4F").order_by("created_at")
       
        serializer= MedServiceDoctorSerializer(visits,many=True)
        return Response(serializer.data,status=status.HTTP_200_OK)


############## END Finance%Module #################
############## MedicalService%Module #################
class MsDoctorsApi(APIView):   
    def get(self,request,ms_pk): 
        ms_doctor = MedicalServiceDoctor.objects.filter(medicalservice_id=ms_pk)
        serializer= MsDoctorSerializer(ms_doctor,many=True)
        return Response(serializer.data,status=status.HTTP_200_OK)
############## END MedicalService%Module #################

############## Patient%Module #################
class AllPatientsApi(APIView):
    # ###@method_decorator(user_passes_test(lambda u: u.has_perm('Management.add_patients'), login_url='/main/login/'))    
    def post(self,request):
        #if not getClinicId(request) : return redirect('/main/login/')
        #all_patients =Patient.objects.all().values('id','fullname','code','last_visit','number_1')
        all_patients = Patient.objects.all().values('id', 'fullname', 'code', 'number_1')
        patients_list = list(all_patients)  # Convert QuerySet to list
        #patients_list = patients_list_*1000
        return JsonResponse(patients_list, safe=False)

class PatientApi(APIView):
    def get_object(self,pk):
        try:
            return Patient.objects.get(pk=pk)
        except Patient.DoesNotExist:
            return None    
    
    # @method_decorator(login_url='/main/login/')     
    def get(self,request,pk): 
        patientObj=self.get_object(pk)
        if patientObj :
            serializedObj= PatientCustomSerializer(patientObj)
            return Response(serializedObj.data,status=status.HTTP_200_OK)
        else : return Response(status=status.HTTP_404_NOT_FOUND)


class PatientExtraInfoApi(APIView):
    def get_object(self,pk):
        try:
            return PatientExtraInfo.objects.get(patient=pk)
        except PatientExtraInfo.DoesNotExist:
            return None  
    #@method_decorator(user_passes_test(lambda u: u.has_perm('screen.add_patients'), login_url='/main/login/'))    
    def post(self,request,pk):#obj pk not patient 
        if not getClinicId(request) : return redirect('/main/login/')
        data = request.data
        data._mutable = True
        data.update({"last_update_by":request.user.id})
        obj=self.get_object(pk)
        if obj : 
            serializedObj= PatientExtraInfoSerializer(obj,data=data,partial=True)
        else :
            serializedObj= PatientExtraInfoSerializer(data=data)
        if serializedObj.is_valid():
            serializedObj.save()
            return Response(status=status.HTTP_200_OK)
        else :return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)


@login_required(login_url='mainApp:login')
def patient_info(request):
    if not getClinicId(request) : return redirect('/main/login/')
    patients =Patient.objects.all().values("id","code","fullname")
    return render(request,"receptionApp/patientPages/patientData/patient_info.html",{
        "patients":patients,})

class PatientInquireApi(APIView): 
    def get(self,request,patient_pk):
        if not getClinicId(request) : return redirect('/main/login/')
        patient =Patient.objects.get(pk=patient_pk)
        patient_age = ageCalculator(patient.birth_date)
        p_visits = PatientVisit.objects.filter(patient=patient_pk).order_by('-created_at')
        p_surgeries = PtSurgery.objects.filter(patient=patient_pk).order_by('-created_at')
        p_info = PatientInfo.objects.filter(patient=patient_pk)
        p_external_payments = PatientExternalPayment.objects.filter(patient=patient_pk)
        p_attachments = PtAttachment.objects.filter(patient=patient_pk)
        marital_status_choices = ChoiceField(choices=MARITAL_STATUS_CHOICES)

        return render(request,"receptionApp/patientPages/patientData/patient_info.html",{
        "patient_age":patient_age,
        "foundWays":FoundWay.objects.all(),
        "locations":Location.objects.all(),
        "nationalities":Nationality.objects.all(),
        "marital_status":marital_status_choices.choices,
        "jobs":PatientJob.objects.all(),
        "patient":patient,"p_visits":p_visits,"p_surgeries":p_surgeries,"p_info":p_info,"p_external_payments":p_external_payments,"p_attachments":p_attachments})

class PatientExternalPaymentsApi(APIView):
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_patients'), login_url='/main/login/'))
    # def get(self,request):
    #     if not getClinicId(request) : return redirect('/main/login/')
    #     all_patients =Patient.objects.all()
    #     all_patients_serialized=PatientSerializer(all_patients,many=True)
    #     return render(request,"mainApp/patientPages/patients.html",{"all_patients":all_patients_serialized.data,'activePage':'Patients'})

    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.add_patients'), login_url='/main/login/'))    
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        request.data._mutable = True
        request.data.update({"created_by":request.user.id})
        serializedObj= PatientExternalPaymentSerializer(data=request.data)
        if serializedObj.is_valid():
            serializedObj.save()
            return Response(status=status.HTTP_201_CREATED)
        else :return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)

class PatientSheetsApi(APIView):
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        return render(request,"receptionApp/patientPages/patientFiles/patient_sheets.html",{'activePage':'PatientSheets'})
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        data=request.data
        day_date = data["day_date"]
        if day_date : 
            visits = PatientVisit.objects.filter(visit_day = day_date , is_sheet_uploaded=False).order_by("entry_order")
            pv_serializer= PVforUploadSheetsSerializer(visits,many=True)

            surgeries = PtSurgery.objects.filter(visit_day = day_date , is_sheet_uploaded=False).order_by("entry_order")
            ps_serializer= PSforUploadSheetsSerializer(surgeries,many=True)
            PSforUploadSheetsSerializer
            return Response({"visits":pv_serializer.data,"surgeries":ps_serializer.data},status=status.HTTP_200_OK)
        else : return Response({},status=status.HTTP_200_OK)
    def put(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        data=request.data
        visit_surgery_id = data["visit_surgery_id"]
        if visit_surgery_id :
            type_code = data["type_code"]
            try : 
                if type_code == "V":obj = PatientVisit.objects.get(id=visit_surgery_id)
                elif type_code == "S":obj = PtSurgery.objects.get(id=visit_surgery_id)
                else :obj=None
                if obj :
                    obj.is_sheet_uploaded = True
                    obj.save()
                    return Response(status=status.HTTP_201_CREATED)
                else:return Response(status=status.HTTP_400_BAD_REQUEST)

            except PatientVisit.DoesNotExist:
                return Response(status=status.HTTP_204_NO_CONTENT)
       


class PatientSurgeriesApi(APIView):
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        all_patients =Patient.objects.all()
        all_patients_serialized=PatientMiniSerializer(all_patients,many=True)
        return render(request,"receptionApp/patientPages/patientFiles/patient_surgeries.html",{
            "all_patients":all_patients_serialized.data,
            'activePage':'PatientSurgeries'})
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        data=request.data
        startDate = data["startDate"]
        startDateTime= datetime.strptime(startDate,"%Y-%m-%d")
        endDate = data["endDate"]
        endDateTime= datetime.strptime(endDate,"%Y-%m-%d").replace(hour=23,minute=59,second=59) 
        doctor = data["doctor"]
        medicalservice=data["medicalservice"]
        if medicalservice == "0" :
            visits = PatientVisit.objects.filter(created_at__gte = startDateTime , created_at__lte=endDateTime,doctor_id=doctor,visit_status="4F").order_by("created_at")
        else : 
            visits = PatientVisit.objects.filter(created_at__gte = startDateTime , created_at__lte=endDateTime,doctor_id=doctor,medicalservice_id=medicalservice,visit_status="4F").order_by("created_at")
       
        serializer= MedServiceDoctorSerializer(visits,many=True)
        return Response(serializer.data,status=status.HTTP_200_OK)
class MedServiceReportDoctor(APIView):
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        medical_services = MedicalService.objects.filter(is_service=True).values("id","name")
        doctors =User.objects.filter(is_doctor=True,is_active=True).values("id","first_name","last_name")
        return render(request,"receptionApp/patientPages/med_service/recp_doctor.html",{
            "medical_services":medical_services,
            "doctors":doctors,
            'activePage':'MedServiceReportDoctor'})
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        data=request.data
        startDate = data["startDate"]
        startDateTime= datetime.strptime(startDate,"%Y-%m-%d")
        endDate = data["endDate"]
        endDateTime= datetime.strptime(endDate,"%Y-%m-%d").replace(hour=23,minute=59,second=59) 
        doctor = data["doctor"]
        medicalservice=data["medicalservice"]
        if medicalservice == "0" :
            visits = PatientVisit.objects.filter(created_at__gte = startDateTime , created_at__lte=endDateTime,doctor_id=doctor,visit_status="4F").order_by("created_at")
        else : 
            visits = PatientVisit.objects.filter(created_at__gte = startDateTime , created_at__lte=endDateTime,doctor_id=doctor,medicalservice_id=medicalservice,visit_status="4F").order_by("created_at")
       
        serializer= MedServiceDoctorSerializer(visits,many=True)
        return Response(serializer.data,status=status.HTTP_200_OK)
############## END Patient%Module #################

############## PatientVisit%Module #################
def get_new_code_value(all_patients):
    max_code = all_patients.aggregate(Max('code'))
    if max_code["code__max"] : new_code_value = int(max_code["code__max"])+1
    else : new_code_value = 1
    return new_code_value

@login_required(login_url='mainApp:login')
def visits(request):
    if not getClinicId(request) : return redirect('/main/login/')
    doctors =User.objects.filter(is_doctor=True,is_active=True).values("id","first_name","last_name")
    doctors_lst = [ d["id"] for d in doctors.values("id")]
    all_patients =Patient.objects.all()
    all_patients_serialized=PatientMiniSerializer(all_patients,many=True)
    timezone_now_today = timezone.now().date()
    #lst_visit_status_i_l = ["1I","3L"]#3nd el doctor w t25ir 
    #lst_visit_status_w = ["2W"]
    medical_services =MedicalService.objects.all().values('id', 'name','price')
    expense_items =ExpenseItem.objects.all().values('id', 'name')
    patient_visits = PatientVisit.objects.filter(
    #Q(visit_day=timezone_now_today) | Q(visit_day=timezone_now_today - timedelta(days=1)), # get today and yesterday visits 
    #Q(visit_day=timezone_now_today) | Q(visit_day__lte=timezone_now_today), # get today and yesterday visits 
    visit_day__lte=timezone_now_today,
    visit_status__in=["1I","3L","2W"],
    )
    #print("timezone_now_today",type(timezone_now_today))
    patient_visits_data = []
    visit_status_i = patient_visits.filter(visit_status="1I")
    visit_status_l = patient_visits.filter(visit_status="3L")
    visit_status_w = patient_visits.filter(visit_status = "2W")
    patient_visits_data.append({
    "visit_status_i":PatientVisitCustomSerializer(visit_status_i,many=True).data,
    "visit_status_l":PatientVisitCustomSerializer(visit_status_l,many=True).data,
    "visit_status_w":PatientVisitCustomSerializer(visit_status_w,many=True).data,
    })
    marital_status_choices = ChoiceField(choices=MARITAL_STATUS_CHOICES)
    return render(request,"receptionApp/pt_visitPages/visits.html",{
        "all_patients":all_patients_serialized.data,
        "doctors":doctors,
        "doctors_lst":doctors_lst,   
        "foundWays":FoundWay.objects.all(),
        "nationalities":Nationality.objects.all(),
        "locations":Location.objects.all(),
        "jobs":PatientJob.objects.all(),
        "medical_services":medical_services,
        "expense_items":expense_items,
        "patient_visits_all_clinic_doctors":patient_visits_data,
         "today_date_value":timezone_now_today.strftime("%Y-%m-%d"),
         "marital_status":marital_status_choices.choices,
        'activePage':'PatientVisit'})

class PatientVisitsApi(APIView):
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_patients'), login_url='/main/login/'))
    # def get(self,request):
    #     if not getClinicId(request) : return redirect('/main/login/')
    #     all_patients =Patient.objects.all()
    #     all_patients_serialized=PatientSerializer(all_patients,many=True)
    #     return render(request,"mainApp/patientPages/patients.html",{"all_patients":all_patients_serialized.data,'activePage':'Patients'})

    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.add_patients'), login_url='/main/login/'))    
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        context = {"service_price": request.data.get("service_price")}
        request.data._mutable = True
        request.data.update({"visit_day":timezone.now().date()})
        request.data.update({"created_by":request.user.id})
        serializedObj= PatientVisitSerializer(data=request.data, context=context)
        if serializedObj.is_valid():
            serializedObj.save()
            return Response(serializedObj.data,status=status.HTTP_201_CREATED)
        else :return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)

class InsideVisitsApi(APIView):
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        inside_visits =PatientVisit.objects.filter(visit_status="1I").order_by("id")
        inside_visits_srl=PatientVisitSerializer(inside_visits,many=True)
        return Response(inside_visits_srl.data,status=status.HTTP_200_OK)

@login_required(login_url='mainApp:login')
def next_visits(request):
    return render(request,"receptionApp/pt_visitPages/next_visits.html",)

class NextVisitsApi(APIView):
    #@method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_patients'), login_url='/main/login/'))
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        day_date=request.GET.get("day_date",None) 
        if day_date :
            patients = Patient.objects.filter(next_consult=day_date).values("pk","id","fullname","number_1","number_2")
            print(patients)
            next_visits = NextVisit.objects.filter(visit_day=day_date)
            patients_data=[]
            for p_dict in patients :
                #p_dict = p.__dict__
                p_next_visit_objs = next_visits.filter(patient_id=p_dict["id"])
                if p_next_visit_objs : 
                    obj = p_next_visit_objs[0]
                    p_dict.update({"emp_comment":obj.emp_comment,"id":obj.id,"emp":obj.created_by.get_full_name()})
                else:p_dict.update({"emp_comment":"","id":"","emp":""})
                p_dict.update({"patient":p_dict["pk"]})
                patients_data.append(p_dict)
            return JsonResponse({"patients_data":patients_data})
        else : return JsonResponse({"patients_data":[]})
    
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        request.data._mutable = True
        request.data.update({"created_by":request.user.id})
        serializeobj= NextVisitSerializer(data=request.data)
        if serializeobj.is_valid():
            serializeobj.save()
            return Response(serializeobj.data,status=status.HTTP_201_CREATED)
        else : return Response(serializeobj.errors,status=status.HTTP_400_BAD_REQUEST)

class NextVisitApi(APIView):
    def put(self,request,pk):
        obj=NextVisit.objects.get(id=pk)
        request.data._mutable = True
        request.data.update({"created_by":request.user.id})
        serializedObj= NextVisitSerializer(obj,data=request.data)
        if serializedObj.is_valid():
            serializedObj.save()
            return Response(status=status.HTTP_200_OK)
        else : return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)

class PatientVisitApi(APIView):
    def get_object(self,pk):
        try:
            return PatientVisit.objects.get(pk=pk)
        except PatientVisit.DoesNotExist:
            return None    
    
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_medicalService'), login_url='/main/login/'))        
    # def get(self,request,pk): 
    #     medical_serviceObj=self.get_object(pk)
    #     if medical_serviceObj :
    #         #return render(request,"mainApp/medical_service.html",{"medical_service":medical_serviceObj,'activePage':'MedicalServices'})
    #         serializeobj= MedicalServiceSerializer(medical_serviceObj)
    #         return Response(serializeobj.data,status=status.HTTP_200_OK)
    #     else : return Response(status=status.HTTP_404_NOT_FOUND)
    
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.edit_medicalService'), login_url='/main/login/'))
    def put(self,request,pk):
        obj=self.get_object(pk)
        newStatus = request.data.get("newStatus")
        if newStatus == "pay" :
            amount_paid = request.data.get("amount_paid",0)
            obj.amount_paid = obj.amount_paid  + int(amount_paid)
            obj.amount_remaining = obj.amount_remaining  - int(amount_paid)
            obj.save()
        if newStatus == '3L' or newStatus == '1I' or newStatus == '4F':
            obj.visit_status = newStatus
            if newStatus == '1I' :
                obj.entry_datetime = timezone.now()
                patient = Patient.objects.get (pk=obj.patient.id)
                #patient.last_visit = datetime.datetime.now()
                patient.last_visit = timezone.now()
                patient.save()
            obj.save()
        if newStatus == 'new' :
            oldVisitObj = obj
            lastVisitObjToday = PatientVisit.objects.filter(visit_day=timezone.now().date()).aggregate(Max('entry_order'))
            oldVisitObj.entry_order = (int(lastVisitObjToday["entry_order__max"]))+1 if lastVisitObjToday["entry_order__max"] else 1
            oldVisitObj.visit_status = "2W"
            oldVisitObj.visit_day=timezone.now().date()
            oldVisitObj.save(update_fields=["entry_order","visit_status","visit_day"])
            #context = {"service_price":newVisitObj.medicalservice.price}
            #serializedObj= PatientVisitSerializer(data=request.data, context=context)
            serializedObj= PatientVisitSerializer(oldVisitObj)
            #serializedObj.save()
            return Response(serializedObj.data,status=status.HTTP_201_CREATED)
        serializedObj= PatientVisitCustomSerializer(obj)
        #if serializedObj.is_valid():
        return Response(serializedObj.data,status=status.HTTP_200_OK)
        #else : return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)
        # else :
        #     if ("name" in serializedObj.errors.keys()):
        #         if("unique" in str(serializedObj.errors)):
        #             list_error+="\n لا يمكن تكرار الإسم , من فضلك ادخل البيانات بطريقة صحيحة"
        #             return Response({"error_messsage":list_error},status=status.HTTP_405_METHOD_NOT_ALLOWED)
            

    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.delete_medicalService'), login_url='/main/login/'))
    def delete(self,request,pk):
        obj=self.get_object(pk)
        if obj :
            try:
                obj.delete()
                return Response(status=status.HTTP_204_NO_CONTENT)
            except Exception as err_msg: 
                    return Response(data ="{}".format(str(err_msg)),status=status.HTTP_405_METHOD_NOT_ALLOWED)
        else : return Response(status=status.HTTP_404_NOT_FOUND)

@login_required(login_url='mainApp:login')
def advance_visits(request):
    timezone_now_today = timezone.now().date()
    #import pdb
    #pdb.set_trace()
    visits = AdvanceReservation.objects.filter(visit_day__gte=timezone_now_today).values("visit_day",).annotate(Count('visit_day',distinct=True),visits=Count('id'))
    week_days = WeekDay.objects.all().values("code","max_patients")
    events =[]
    import pdb 
    #pdb.set_trace()
    for c in visits :
        week_day = week_days.filter(code=c["visit_day"].weekday()).first()
        if week_day : 
            color = '#f56954' if c["visits"] >= week_day["max_patients"] else '#00a65a'#green (#00a65a)
        else : color ='#00a65a'
        events.append(
           {
           "title"         : c["visits"],
           "start"          : c["visit_day"].strftime("%Y-%m-%d"),
           "allDay"         : "true",
           "backgroundColor": color, #Success (green)
           "borderColor"    : color, #Success (green)
        }
        )
    return render(request,"receptionApp/advance_visitsPages/advance_visits.html",{"events":events})

class AdvanceVisitsApi(APIView):
    #@method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_patients'), login_url='/main/login/'))
    def get(self,request,visit_day):
        if not getClinicId(request) : return redirect('/main/login/')
        #pdb.set_trace()
        #doctors =User.objects.filter(Q(is_doctor=True) | Q(is_specialist=True) , is_active=True).values("id","first_name","last_name","is_doctor","is_specialist")
        #doctors =User.objects.filter(is_active=True,is_doctor=True).values("id","first_name","last_name","is_doctor")
        #all_patients =Patient.objects.all()
        #all_patients_serialized=PatientMiniSerializer(all_patients,many=True)
        #medical_services =MedicalService.objects.all().values('id', 'name','price',)
        reservations = AdvanceReservation.objects.filter(visit_day=visit_day).order_by("hour_slot")
        hour_slot_reserved = reservations.values_list("hour_slot",flat=True)
        #marital_status_choices = ChoiceField(choices=MARITAL_STATUS_CHOICES)
        return render(request,"receptionApp/advance_visitsPages/advance_visits_day.html",{
            "visit_day":visit_day,
            #"all_patients":all_patients_serialized.data,
            #"doctors":doctors,
            #"medical_services":medical_services,
            #"foundWays":FoundWay.objects.all(),
            #"locations":Location.objects.all(),
            "hour_slots":HourSlot.objects.filter(is_active=True).values('id', 'name',).order_by('order'),
            "reservations":reservations,
            "hour_slot_reserved":hour_slot_reserved,
            "jobs":PatientJob.objects.all(),
            #"marital_status":marital_status_choices.choices,
            #"new_code_value":get_new_code_value(all_patients),
            'activePage':'AdvanceVisits'})
    
    def post(self,request,visit_day):
        if not getClinicId(request) : return redirect('/main/login/')
        request.data._mutable = True
        request.data.update({"created_by":request.user.id})
        request.data.update({"visit_day":visit_day})
        serializer= AdvanceReservationSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data,status=status.HTTP_201_CREATED)
        else : return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)

class AdvanceVisitApi(APIView):
    def get_object(self,pk):
        try:
            return AdvanceReservation.objects.get(pk=pk)
        except AdvanceReservation.DoesNotExist:
            return None  
    def put(self,request,pk):
        obj=self.get_object(pk)
        if obj :
            data = request.data
            if "action" in data and data["action"] == "editReservation" : 
                data._mutable = True
                data.update({"created_by":request.user.id})
            serializedObj= AdvanceReservationSerializer(obj,data=data,partial=True)
            if serializedObj.is_valid():
                serializedObj.save()
                return Response(status=status.HTTP_200_OK)
            else : return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)
        else : return Response(status=status.HTTP_404_NOT_FOUND)
    
    def delete(self,request,pk):
        obj=self.get_object(pk)
        if obj :
            try:
                obj.delete()
                return Response(status=status.HTTP_204_NO_CONTENT)
            except Exception as err_msg: 
                return Response(data ="{}".format(str(err_msg)),status=status.HTTP_405_METHOD_NOT_ALLOWED)
        else : return Response(status=status.HTTP_404_NOT_FOUND)

class PrintVisitApi(APIView):
    def post(self,request):
        visit_id=request.data.get("visit_id")
        context={}
        if visit_id : 
            template_name = "clinicReports/{}/visit.html".format(request.session['reports_code'])
            patientVisitObj = PatientVisit.objects.get(pk=visit_id)
            context.update({"pV":PatientVisitPrintSerializer(patientVisitObj).data})
            return render(request,template_name,context)
        else : return redirect('receptionApp:welcome')

from django.template.loader import render_to_string
from einvoiceApp.models import PvEInvoice,PsEInvoice
class PrintVisitInvoiceApi(APIView):    
    # @method_decorator(login_url='/main/login/')     
    def post(self,request,visit_id): 
        user = request.user
        original_vi = PatientVisit.objects.get(id=visit_id)
        if not original_vi.invoice_serial :
            max_invoice_serial= PatientVisit.objects.aggregate(max_invoice_serial=Coalesce(Max('invoice_serial'),0))['max_invoice_serial']
            original_vi.invoice_serial = int(max_invoice_serial)+1
            original_vi.invoice_last_update_by = user
            original_vi.is_e_invoice_request = True
            original_vi.save()
            pve_invoice, created = PvEInvoice.objects.get_or_create(pv=original_vi)
            # pve_invoice.is_e_invoice_registered =True
            # pve_invoice.registered_by_id =user_id
            # pve_invoice.registered_at =timezone.now()
            # pve_invoice.save()
        vi_serializer= PatientVisitInvoiceSerializer(original_vi,many=False)
        context={}
        template_name = "clinicReports/{}/visit_invoice.html".format(request.session['reports_code'])
        context.update({"visit_invoice":vi_serializer.data,"code":"visit"})
        html_code = render_to_string(template_name,context)
        return Response({"html_code":html_code},status=status.HTTP_200_OK)


class PrintSurgeryInvoiceApi(APIView):    
    # @method_decorator(login_url='/main/login/')     
    def post(self,request,surgery_id): 
        user = request.user
        original_vi = PtSurgery.objects.get(id=surgery_id)
        if not original_vi.invoice_serial :
            max_invoice_serial_v= PatientVisit.objects.aggregate(max_invoice_serial=Coalesce(Max('invoice_serial'),0))['max_invoice_serial']
            max_invoice_serial_s= PtSurgery.objects.aggregate(max_invoice_serial=Coalesce(Max('invoice_serial'),0))['max_invoice_serial']
            max_invoice_serial = max(max_invoice_serial_v,max_invoice_serial_s)
            original_vi.invoice_serial = int(max_invoice_serial)+1
            original_vi.invoice_last_update_by = user
            original_vi.is_e_invoice_request = True
            original_vi.save()
            pse_invoice, created = PsEInvoice.objects.get_or_create(ps=original_vi)
            # pve_invoice.is_e_invoice_registered =True
            # pve_invoice.registered_by_id =user_id
            # pve_invoice.registered_at =timezone.now()
            # pve_invoice.save()
        vi_serializer= PatientSurgeryInvoiceSerializer(original_vi,many=False)
        context={}
        template_name = "clinicReports/{}/visit_invoice.html".format(request.session['reports_code'])
        context.update({"visit_invoice":vi_serializer.data,"code":"surgery"})
        html_code = render_to_string(template_name,context)
        return Response({"html_code":html_code},status=status.HTTP_200_OK)
############## END PatientVisit%Module #################

############## PatientSurgery%Module #################

from surgeryApp.serializers import PtSurgeryCustomSerializer,PtSurgerySerializer,PtSurgeryCreateSerializer

@login_required(login_url='mainApp:login')
def surgeries(request):
    if not getClinicId(request) : return redirect('/main/login/')
    doctors =User.objects.filter(is_doctor=True,is_active=True).values("id","first_name","last_name")
    doctors_lst = [ d["id"] for d in doctors.values("id")]
    all_patients =Patient.objects.all()
    all_patients_serialized=PatientMiniSerializer(all_patients,many=True)
    timezone_now_today = timezone.now().date()
    #lst_visit_status_i_l = ["1I","3L"]#3nd el doctor w t25ir 
    #lst_visit_status_w = ["2W"]
    surgeries =Surgery.objects.all().values('id', 'name','price')
    expense_items =ExpenseItem.objects.all().values('id', 'name')
    patient_surgeries = PtSurgery.objects.filter(
    #Q(visit_day=timezone_now_today) | Q(visit_day=timezone_now_today - timedelta(days=1)), # get today and yesterday visits 
    #Q(visit_day=timezone_now_today) | Q(visit_day__lte=timezone_now_today), # get today and yesterday visits 
    visit_day__lte=timezone_now_today,
    visit_status__in=["1I","3L","2W"],
    )
    #print("timezone_now_today",type(timezone_now_today))
    patient_surgeries_data = []
    visit_status_i = patient_surgeries.filter(visit_status="1I")
    visit_status_l = patient_surgeries.filter(visit_status="3L")
    visit_status_w = patient_surgeries.filter(visit_status = "2W")
    patient_surgeries_data.append({
    "visit_status_i":PtSurgeryCustomSerializer(visit_status_i,many=True).data,
    "visit_status_l":PtSurgeryCustomSerializer(visit_status_l,many=True).data,
    "visit_status_w":PtSurgeryCustomSerializer(visit_status_w,many=True).data,
    })
    marital_status_choices = ChoiceField(choices=MARITAL_STATUS_CHOICES)
    return render(request,"receptionApp/surgeriesPages/surgeries.html",{
        "all_patients":all_patients_serialized.data,
        "doctors":doctors,
        "doctors_lst":doctors_lst,   
        "foundWays":FoundWay.objects.all(),
        "nationalities":Nationality.objects.all(),
        "locations":Location.objects.all(),
        "jobs":PatientJob.objects.all(),
        "surgeries":surgeries,
        "expense_items":expense_items,
        "patient_surgeries_all_clinic_doctors":patient_surgeries_data,
         "today_date_value":timezone_now_today.strftime("%Y-%m-%d"),
         "marital_status":marital_status_choices.choices,
        'activePage':'PatientVisit'})

class PatientSurgeriesCurrentApi(APIView):
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_patients'), login_url='/main/login/'))
    # def get(self,request):
    #     if not getClinicId(request) : return redirect('/main/login/')
    #     all_patients =Patient.objects.all()
    #     all_patients_serialized=PatientSerializer(all_patients,many=True)
    #     return render(request,"mainApp/patientPages/patients.html",{"all_patients":all_patients_serialized.data,'activePage':'Patients'})

    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.add_patients'), login_url='/main/login/'))    
    def post(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        context = {"service_price": request.data.get("service_price")}
        request.data._mutable = True
        request.data.update({"visit_day":timezone.now().date()})
        request.data.update({"created_by":request.user.id})
        import pdb
        #pdb.set_trace()
        serializedObj= PtSurgeryCreateSerializer(data=request.data, context=context)
        if serializedObj.is_valid():
            serializedObj.save()
            return Response(serializedObj.data,status=status.HTTP_201_CREATED)
        else :return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)


class PtSurgeryCurrentApi(APIView):
    def get_object(self,pk):
        try:
            return PtSurgery.objects.get(pk=pk)
        except PtSurgery.DoesNotExist:
            return None    
    
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.view_medicalService'), login_url='/main/login/'))        
    # def get(self,request,pk): 
    #     medical_serviceObj=self.get_object(pk)
    #     if medical_serviceObj :
    #         #return render(request,"mainApp/medical_service.html",{"medical_service":medical_serviceObj,'activePage':'MedicalServices'})
    #         serializeobj= MedicalServiceSerializer(medical_serviceObj)
    #         return Response(serializeobj.data,status=status.HTTP_200_OK)
    #     else : return Response(status=status.HTTP_404_NOT_FOUND)
    
    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.edit_medicalService'), login_url='/main/login/'))
    def put(self,request,pk):
        obj=self.get_object(pk)
        newStatus = request.data.get("newStatus")
        if newStatus == "pay" :
            amount_paid = request.data.get("amount_paid",0)
            obj.amount_paid = obj.amount_paid  + int(amount_paid)
            obj.amount_remaining = obj.amount_remaining  - int(amount_paid)
            obj.save()
        if newStatus == '3L' or newStatus == '1I' or newStatus == '4F':
            obj.visit_status = newStatus
            # if newStatus == '1I' :
            #     obj.entry_datetime = timezone.now()
            #     patient = Patient.objects.get (pk=obj.patient.id)
            #     #patient.last_visit = datetime.datetime.now()
            #     patient.last_visit = timezone.now()
            #     patient.save()
            obj.save()
        if newStatus == 'new' :
            oldVisitObj = obj
            lastVisitObjToday = PtSurgery.objects.filter(visit_day=timezone.now().date()).aggregate(Max('entry_order'))
            oldVisitObj.entry_order = (int(lastVisitObjToday["entry_order__max"]))+1 if lastVisitObjToday["entry_order__max"] else 1
            oldVisitObj.visit_status = "2W"
            oldVisitObj.visit_day=timezone.now().date()
            oldVisitObj.save(update_fields=["entry_order","visit_status","visit_day"])
            #context = {"service_price":newVisitObj.medicalservice.price}
            #serializedObj= PatientVisitSerializer(data=request.data, context=context)
            serializedObj= PtSurgerySerializer(oldVisitObj)
            #serializedObj.save()
            return Response(serializedObj.data,status=status.HTTP_201_CREATED)
        serializedObj= PtSurgeryCustomSerializer(obj)
        #if serializedObj.is_valid():
        return Response(serializedObj.data,status=status.HTTP_200_OK)
        #else : return Response(serializedObj.errors,status=status.HTTP_400_BAD_REQUEST)
        # else :
        #     if ("name" in serializedObj.errors.keys()):
        #         if("unique" in str(serializedObj.errors)):
        #             list_error+="\n لا يمكن تكرار الإسم , من فضلك ادخل البيانات بطريقة صحيحة"
        #             return Response({"error_messsage":list_error},status=status.HTTP_405_METHOD_NOT_ALLOWED)
            

    # @method_decorator(user_passes_test(lambda u: u.has_perm('screen.delete_medicalService'), login_url='/main/login/'))
    def delete(self,request,pk):
        obj=self.get_object(pk)
        if obj :
            try:
                obj.delete()
                return Response(status=status.HTTP_204_NO_CONTENT)
            except Exception as err_msg: 
                    return Response(data ="{}".format(str(err_msg)),status=status.HTTP_405_METHOD_NOT_ALLOWED)
        else : return Response(status=status.HTTP_404_NOT_FOUND)

class InsideSurgeriesApi(APIView):
    def get(self,request):
        if not getClinicId(request) : return redirect('/main/login/')
        inside_visits =PtSurgery.objects.filter(visit_status="1I").order_by("id")
        inside_visits_srl=PtSurgerySerializer(inside_visits,many=True)
        return Response(inside_visits_srl.data,status=status.HTTP_200_OK)
############## END PatientVisit%Module #################


