#from typing_extensions import Required
from rest_framework import serializers
from .models import * 
from django.contrib.auth.models import Group , Permission

############## User%Module #################

class PermissionSerializer(serializers.ModelSerializer):        
    class Meta:
        model = Permission
        fields="__all__"
class GroupSerializer(serializers.ModelSerializer):        
    class Meta:
        model = Group
        fields = ['id', 'name','clinic']
class GroupWithPermissionsSerializer(serializers.ModelSerializer):        
    permissions = PermissionSerializer(many=True) 
    class Meta:
        model = Group
        fields = ['id', 'name','permissions']
class ChoiceField(serializers.ChoiceField):
    def to_representation(self, obj):
        if obj == '' and self.allow_blank:
            return obj
        return self._choices[obj]
class GroupPermissionSerializer(serializers.ModelSerializer):
            
    def update(self, instance, validated_data):
        if 'permissions' in validated_data:
            instance.permis(validated_data['permissions'])
            instance.save()
            return instance    

    class Meta:
        model = User
        fields=("permissions",)
class UserSerializer(serializers.ModelSerializer):

    def create(self, validated_data):
        user = User(
        username=validated_data['username'],
        first_name=validated_data['first_name'],
        last_name=validated_data['last_name'],
        is_active=validated_data['is_active'],
        is_doctor=validated_data['is_doctor'],
        created_by_id = (self.context.get("created_by")),)
        user.set_password(validated_data['password'])
        if (self.context.get("group_id"))== '1' : 
            user.is_superuser = True
            user.is_staff = True
        else :
            user.is_superuser = False
            user.is_staff = False
        user.save()
        return user

    class Meta:
        model = User
        fields = ('id','username',"first_name",'last_name','password','is_active',"created_by","is_doctor")   
    def to_representation(self, instance):
        return super(UserSerializer, self).to_representation(instance) 
class UserWithoutPasswordSerializer(serializers.ModelSerializer):

    def update(self, instance, validated_data):
        instance.username=validated_data['username']
        instance.first_name=validated_data['first_name']
        instance.last_name=validated_data['last_name']
        instance.is_active=validated_data['is_active']
        instance.is_doctor=validated_data['is_doctor']
        instance.created_by_id = self.context.get("created_by")
        if (self.context.get("group_id"))== '1' : 
            instance.is_superuser = True
            instance.is_staff = True
        else :
            instance.is_superuser = False
            instance.is_staff = False
        instance.save()
        return instance  

    class Meta:
        model = User
        fields = ('id','username',"first_name",'last_name','is_active',"created_by","is_doctor")   
    def to_representation(self, instance):
        return super(UserSerializer, self).to_representation(instance) 
class UserPasswordSerializer(serializers.ModelSerializer):
            
    def update(self, instance, validated_data):
        if 'password' in validated_data:
            instance.set_password(validated_data['password'])
            instance.save()
            return instance    

    class Meta:
        model = User
        fields=("password",)  
class UserSerializerMini(serializers.ModelSerializer):
    class Meta:
        model = User
        fields=("id","username","first_name",) 
class UserSerializerCust(serializers.ModelSerializer):
    groups = GroupSerializer(many=True)
    class Meta:
        model = User
        fields=('id',"last_login","is_superuser","username","is_doctor","first_name",
        "last_name","email","is_staff","is_active","date_joined","created_by","groups")  
    def to_representation(self, instance):
        #self.fields['group'] =  GroupSerializer(read_only=True)
        return super(UserSerializerCust, self).to_representation(instance)

############## END User%Module #################

############## Finance%Module #################

class ExpenseItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = ExpenseItem
        fields="__all__"

class MedServiceDoctorSerializer(serializers.ModelSerializer):
    creation_day= serializers.SerializerMethodField()
    creation_time= serializers.SerializerMethodField()
    #visit_type_val= serializers.SerializerMethodField()
    #visit_type= ChoiceField(choices=VISIT_TYPES_CHOICES)
    class Meta:
        model = PatientVisit
        #fields=("patient","amount_required","creation_day","creation_time","visit_type")
        fields=("patient","amount_required","creation_day","creation_time","medicalservice")
    def get_creation_day(self, obj):
        return obj.created_at.strftime("%Y-%m-%d")
    def get_creation_time(self, obj):
        return obj.created_at.strftime("%H:%M")
    # def get_visit_type_val(self, obj):
    #     return obj.visit_type
    def to_representation(self, instance):
        obj = super().to_representation(instance)
        obj['patient'] = instance.patient.fullname
        obj['medicalservice'] = instance.medicalservice.name
        #obj['visit_type']= instance.patient.get_displa
        return obj

class MedServiceHalfSerializer(serializers.ModelSerializer):
    creation_day= serializers.SerializerMethodField()
    creation_time= serializers.SerializerMethodField()
    amount_required = serializers.SerializerMethodField()#return half amount as integer
    #visit_type_val= serializers.SerializerMethodField()
    #visit_type= ChoiceField(choices=VISIT_TYPES_CHOICES)
    class Meta:
        model = PatientVisit
        #fields=("patient","amount_required","creation_day","creation_time","visit_type")
        fields=("patient","amount_required","creation_day","creation_time","medicalservice")
    def get_creation_day(self, obj):
        return obj.created_at.strftime("%Y-%m-%d")
    def get_creation_time(self, obj):
        return obj.created_at.strftime("%H:%M")
    # def get_visit_type_val(self, obj):
    #     return obj.visit_type
    def get_amount_required(self, obj):
        # return obj.amount_required * 0.5  # 50% return float
        return obj.amount_required // 2 #return integer
    def to_representation(self, instance):
        obj = super().to_representation(instance)
        obj['patient'] = instance.patient.fullname
        obj['medicalservice'] = instance.medicalservice.name
        #obj['visit_type']= instance.patient.get_displa
        return obj


class PSforUploadSheetsSerializer(serializers.ModelSerializer):
    #creation_day= serializers.SerializerMethodField()
    p_fullname = serializers.CharField(source="patient.fullname")
    surgery = serializers.CharField(source="surgery.name")
    class Meta:
        model = PatientVisit
        fields=("id","patient","p_fullname","entry_order","surgery")

class PVforUploadSheetsSerializer(serializers.ModelSerializer):
    #creation_day= serializers.SerializerMethodField()
    p_fullname = serializers.CharField(source="patient.fullname")
    medicalservice = serializers.CharField(source="medicalservice.name")
    class Meta:
        model = PatientVisit
        fields=("id","patient","p_fullname","entry_order","medicalservice")

    # def to_representation(self, instance):
    #     obj = super().to_representation(instance)
    #     obj['medicalservice'] = instance.medicalservice.name
    #     return obj

class CheckupVisitSerializer(serializers.ModelSerializer):
    creation_day= serializers.SerializerMethodField()
    creation_time= serializers.SerializerMethodField()
    eye_count= serializers.SerializerMethodField()
    class Meta:
        model = PatientVisit
        fields=("doctor","patient","medicalservice","amount_required","eye_count","created_by","creation_day","creation_time",)
    def get_creation_day(self, obj):
        return obj.created_at.strftime("%Y-%m-%d")
    def get_creation_time(self, obj):
        return obj.created_at.strftime("%H:%M")
    def get_eye_count(self, obj):
        return obj.medicalservice.eye_count
    def to_representation(self, instance):
        obj = super().to_representation(instance)
        obj['patient'] = instance.patient.fullname
        obj['medicalservice'] = instance.medicalservice.name
        obj['doctor'] = instance.doctor.get_full_name()
        obj['created_by'] = instance.created_by.get_full_name()
        return obj
############## END Finance%Module #################
############## AdditionalInfo%Module #################
class FoundWaySerializer(serializers.ModelSerializer):
    class Meta:
        model = FoundWay
        fields="__all__"

class NationalitySerializer(serializers.ModelSerializer):
    class Meta:
        model = Nationality
        fields="__all__"

class LocationSerializer(serializers.ModelSerializer):
    nationality_name = serializers.CharField(source="nationality.name",default="",read_only=True)
    class Meta:
        model = Location
        fields="__all__"

class CitySerializer(serializers.ModelSerializer):
    nationality_name = serializers.CharField(source="location.nationality.name",default="",read_only=True)
    location_name = serializers.CharField(source="location.name",default="",read_only=True)
    nationality_id = serializers.CharField(source="location.nationality.id",default="",read_only=True)

    class Meta:
        model = City
        fields="__all__"

class PatientJobSerializer(serializers.ModelSerializer):
    class Meta:
        model = PatientJob
        fields="__all__"
class HourSlotSerializer(serializers.ModelSerializer):
    class Meta:
        model = HourSlot
        fields="__all__"


class WeekDaySerializer(serializers.ModelSerializer):
    class Meta:
        model = WeekDay
        fields="__all__"
############## END AdditionalInfo%Module #################
############## MedicalService%Module #################

# class DoctorSerializer(serializers.ModelSerializer):
#     full_name = serializers.SerializerMethodField()
#     class Meta:
#         model = User
#         fields=["id","full_name"]
#     def get_full_name(self, obj):
#        return obj.get_full_name()
class MedicalServiceDoctorSerializer(serializers.ModelSerializer):
    class Meta:
        model = MedicalServiceDoctor
        fields=["medicalservice","doctor_price"]
class MedicalServiceSerializer(serializers.ModelSerializer):
    class Meta:
        model = MedicalService
        fields="__all__"
class MedicalServiceMiniSerializer(serializers.ModelSerializer):
    class Meta:
        model = MedicalService
        fields=("id",'name')


############## END MedicalService%Module #################

############## Patient%Module #################

class PatientSerializer(serializers.ModelSerializer):
    #last_visit = serializers.DateTimeField(format="%d/%m/%Y",required=False)
    last_visit = serializers.DateTimeField(format="%Y-%m-%d",required=False)
    location_str = serializers.SerializerMethodField()
    found_way_str = serializers.SerializerMethodField()
    #next_consult = serializers.DateField(format="%d-%m-%Y",required=False)
    #new_code_value = serializers.SerializerMethodField()
    # company_string = serializers.SerializerMethodField()
    class Meta:
        model = Patient
        fields="__all__"
        #read_only_fields = ('new_code_value')
    def to_representation(self, instance):
        obj = super().to_representation(instance)
        # obj['last_visit'] = instance.last_visit.strftime("%Y-%m-%d    %H:%M")
        #if obj['last_visit'] : obj['last_visit'] = instance.last_visit.strftime("%Y-%m-%d")
        #else : obj['last_visit'] = "لا توجد زيارات سابقة"
        if obj['next_consult'] : obj['next_consult'] = instance.next_consult.strftime("%Y-%m-%d")
        else : obj['next_consult'] = "غير محدد"
        return obj
    def get_location_str(self, obj):
        if obj.location :  return obj.location.name
        else : return ""
    def get_found_way_str(self, obj):
        if obj.found_way :  return obj.found_way.name
        else : return ""
    # def get_new_code_value(self, obj):
    #     max_code = Patient.objects.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
    # def get_org_string(self, obj):
    #     if obj.organization :  return obj.organization.name
    #     else : return ""

class PatientInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = PatientInfo
        fields="__all__"        
class PatientMiniSerializer(serializers.ModelSerializer):
    class Meta:
        model = Patient
        fields=["id","fullname","code"]
class PatientCustomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Patient
        fields=["id","fullname","birth_date","is_male"]
class PtAttachmentSerializer(serializers.ModelSerializer):
    creation_day= serializers.SerializerMethodField()
    class Meta:
        model = PtAttachment
        fields="__all__"
        read_only_fields=("creation_day",)
        extra_kwargs = {"pa_file":{"required":True}}
    
    def to_representation(self, instance):
        res = super().to_representation(instance)
        res['other_attach'] = ExtraPtAttachmentSerializer(ExtraPtAttachment.objects.filter(pt_attachment=instance),many=True).data
        return res

    def get_creation_day(self, obj):
        #return obj.created_at.strftime("%Y-%m-%d")
        #return obj.created_at.strftime("%d/%m/%Y")
        return obj.created_at.strftime("%Y/%m/%d")

class PtAttachmentUpdateSerializer(serializers.ModelSerializer):
    patient = serializers.SerializerMethodField(required=False)
    class Meta:
        model = PtAttachment
        fields="__all__"


class ExtraPtAttachmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = ExtraPtAttachment
        fields="__all__"
class CommonDiseaseSerializer(serializers.ModelSerializer):
    class Meta:
        model = CommonDisease
        fields="__all__"

############## END Patient%Module #################

############## PatientVisit%Module #################
class PatientVisitForInvSerializer(serializers.ModelSerializer):
    class Meta:
        model = PatientVisit
        fields="__all__"
class PatientVisitSerializer(serializers.ModelSerializer):
    visit_status_string = serializers.SerializerMethodField()
    patient_string = serializers.SerializerMethodField()
    medicalservice_string = serializers.SerializerMethodField()
    medicalservice_value = serializers.SerializerMethodField()
    entry_datetime = serializers.DateTimeField(format="%d/%m/%Y %H:%M")
    created_at = serializers.DateTimeField(format="%d-%m-%Y %H:%M")

    class Meta:
        model = PatientVisit
        fields="__all__"
        read_only_fields = ('visit_status_string', 'patient_string',"medicalservice_string","medicalservice_value")

    def get_visit_status_string(self, obj):
        return obj.get_visit_status_display()        
    def get_patient_string(self, obj):
        return obj.patient.fullname
    def get_medicalservice_string(self, obj):
        return obj.medicalservice.name
    def get_medicalservice_value(self, obj):
        return obj.medicalservice.price
class PatientDetailVisitSerializer(serializers.ModelSerializer):
    def create(self, validated_data):
        amount_paid = int(validated_data['amount_paid'])
        amount_required = int(validated_data['amount_required'])
        amount_remaining = amount_required - amount_paid
        patient_=validated_data['patient']
        lastVisitObjToday = PatientVisit.objects.filter(visit_day=validated_data["visit_day"]).aggregate(Max('entry_order'))
        entry_order = (int(lastVisitObjToday["entry_order__max"]))+1 if lastVisitObjToday["entry_order__max"] else 1
        visitObj = PatientVisit(
        patient=patient_,
        medicalservice=validated_data['medicalservice'],
        amount_paid=amount_paid,
        amount_required=amount_required,
        amount_remaining = amount_remaining,
        visit_day = validated_data["visit_day"],
        visit_status = validated_data["visit_status"],
        entry_datetime = validated_data["entry_datetime"],
        doctor_discount=validated_data["doctor_discount"],
        entry_order = entry_order,
        created_by = validated_data["created_by"])
        patient_.last_visit = timezone.now()
        # if amount_remaining > 0 :
        #     patient_balance  = patient_.debt
        #     patient_.debt = patient_balance + amount_remaining
        # if amount_paid > amount_required : 
        #     patient_balance  = patient_.debt
        #     patient_.debt = patient_balance -  (amount_paid - amount_required)
        patient_.save()
        visitObj.save()
        return visitObj
        
    class Meta:
        model = PatientVisit
        fields="__all__"
class PatientVisitMiniSerializer(serializers.ModelSerializer):
    medicalservice_string = serializers.SerializerMethodField()

    class Meta:
        model = PatientVisit
        fields="__all__"
        read_only_fields = ("id",'visit_day', 'doctor_notes',"medicalservice_string","doctor","visit_type")

    def get_medicalservice_string(self, obj):
        return obj.medicalservice.name
    def to_representation(self, instance):
        obj = super().to_representation(instance)
        obj['doctor'] = instance.doctor.get_full_name()
        return obj
'''
class CanceledVisitSerializer(serializers.ModelSerializer):
    class Meta:
        model = CanceledVisit
        fields="__all__"
class CanceledVisitCustomSerializer(serializers.ModelSerializer):
    creation_day= serializers.SerializerMethodField()
    creation_time= serializers.SerializerMethodField()
    class Meta:
        model = CanceledVisit
        fields=("cancel_reason","patient","created_by","creation_day","creation_time",)
    def get_creation_day(self, obj):
        return obj.created_at.strftime("%Y-%m-%d")
    def get_creation_time(self, obj):
        return obj.created_at.strftime("%H:%M")
    def to_representation(self, instance):
        obj = super().to_representation(instance)
        obj['patient'] = instance.patient.fullname
        obj['created_by'] = instance.created_by.get_full_name()
        return obj
'''
############## END PatientVisit%Module #################

############## Prescription%Module #################

class DrugSerializer(serializers.ModelSerializer):
    class Meta:
        model = Drug
        fields="__all__"
class DrugMiniSerializer(serializers.ModelSerializer):
    class Meta:
        model = Drug
        fields=("name_en","name_ar","id")
class RadiologySerializer(serializers.ModelSerializer):
    class Meta:
        model = Radiology
        fields="__all__"
class MedicalTestSerializer(serializers.ModelSerializer):
    class Meta:
        model = MedicalTest
        fields="__all__"
class TimeTodoSerializer(serializers.ModelSerializer):
    class Meta:
        model = TimeTodo
        fields="__all__"
class PresDrugItemSerializer(serializers.ModelSerializer):
    item_type_string = serializers.SerializerMethodField()
    item_type_model = serializers.SerializerMethodField()
    item_name_string = serializers.SerializerMethodField()
    todo_string = serializers.SerializerMethodField()
    
    class Meta:
        model = PresDrugItem
        fields="__all__"
        read_only_fields = ("item_type_string","item_type_model",'item_name_string', 'todo_string')

    def get_item_name_string(self, obj):
        return obj.drug.name_en
    def get_todo_string(self, obj):
        return obj.time_todo.name
    def get_item_type_string(self, obj):
        return "دواء"
    def get_item_type_model(self, obj):
        return "Drug"
class PresRadiologyItemSerializer(serializers.ModelSerializer):
    item_type_string = serializers.SerializerMethodField()
    item_type_model = serializers.SerializerMethodField()
    item_name_string = serializers.SerializerMethodField()
    todo_string = serializers.SerializerMethodField()

    class Meta:
        model = PresRadiologyItem
        fields="__all__"
        read_only_fields = ("item_type_string","item_type_model",'item_name_string', 'todo_string')

    def get_item_name_string(self, obj):
        return "{}".format(obj.radiology.name)
        #return "{} {} ".format(obj.radiology.name,obj.radiology.descrption)
    def get_todo_string(self, obj):
        return obj.time_todo.name
    def get_item_type_string(self,obj):
        return "أشعة"
    def get_item_type_model(self,obj):
        return "Radiology"
class PresTestItemSerializer(serializers.ModelSerializer):
    item_type_string = serializers.SerializerMethodField()
    item_type_model = serializers.SerializerMethodField()
    item_name_string = serializers.SerializerMethodField()
    todo_string = serializers.SerializerMethodField()

    class Meta:
        model = PresTestItem
        fields="__all__"
        read_only_fields = ("item_type_string","item_type_model",'item_name_string', 'todo_string')
    
    def get_item_name_string(self, obj):
        return "{}".format(obj.medical_test.name)
        #return "{} {} ".format(obj.medical_test.name,obj.medical_test.descrption)
    def get_todo_string(self, obj):
        return obj.time_todo.name
    def get_item_type_string(self,obj):
        return  "تحليل"
    def get_item_type_model(self,obj):
        return "Test"

############## END Prescription%Module ################

