from rest_framework import serializers
from .models import *
from django.db.models import *
import phonenumbers
from django.http import JsonResponse
from mama_care_api.settings import languageKey
from datetime import datetime
from common.common import validatePassword, generateToken, getSubscriptionInfo,validateParentId, getMedicalProfile
from basic.serializers import *
from user_profile.models import FinancialProfile,MedicalProfile
from user_profile.serializers import FinancialProfileSerializer

# Forget or Change Password

class ForgetOrChangePasswordSerializer(serializers.Serializer):
    flag = serializers.CharField()
    phone = serializers.CharField()
    newPassword = serializers.CharField()
    confirmPassword = serializers.CharField()
    oldPassword = serializers.CharField(default="")

    def validate(self, data):
        errorMessage = ""

        phone = None
        if "phone" in data:
            phone = data["phone"]
        else:
            errorMessage = "Phone is required"

        newPassword = None
        if "newPassword" in data:
            newPassword = data["newPassword"]
            if validatePassword(newPassword) != True:
                errorMessage = "Password must consists of 6 digits only"
        else:
            errorMessage = "New Password is required"

        confirmPassword = None
        if "confirmPassword" in data:
            confirmPassword = data["confirmPassword"]
        else:
            errorMessage = "Confirm Password is required"

        oldPassword = None
        flag = None
        if "flag" in data:
            flag = data["flag"]
            if flag == "change":
                if "oldPassword" in data:
                    oldPassword = data["oldPassword"]
                else:
                    errorMessage = "Old Password is required"
        else:
            errorMessage = "Flag is required"

        if newPassword != confirmPassword:
            errorMessage = "Mismatch Password"

        parentList = Parent.objects.filter(phone=phone)
        if parentList.__len__() > 0:
            selected = parentList[0]
            if flag == "change":
                if oldPassword is not None:
                    if selected.password != oldPassword:
                        errorMessage = "Invalid old Password"
                else:
                    errorMessage = "Old Password is Required"
        else:
            errorMessage = "No records found by phone"

        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})

        return data

    def create(self, validated_data):
        errorMessage = ""
        phone = validated_data["phone"]
        newPassword = validated_data["newPassword"]
        parentList = Parent.objects.filter(phone=phone)
        if parentList.__len__() > 0:
            selected = parentList[0]
            if selected is not None:
                selected.password = newPassword
                selected.save()
            else:
                errorMessage = "Not Updated"
        else:
            errorMessage = "No records found by phone"
            
        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})
        else:
            return JsonResponse({})


class SignUpSerializer(serializers.Serializer):
    isTryingToBePregnant = serializers.BooleanField()
    dueDateOrBirthday = serializers.DateTimeField()
    phone = serializers.CharField()
    password = serializers.CharField()
    languageId = serializers.IntegerField()

    def validatePhone(self, phone):
        isParsed = True
        try:
            parsed_number = phonenumbers.parse(phone, None)
        except:
            isParsed = False

        if isParsed:
            if phonenumbers.is_valid_number(parsed_number):
                return True
        return False

    def checkPhoneIsNotExists(self, phone):
        count = Parent.objects.filter(phone=phone).count()
        if count > 0:
            return False
        return True

    def checkPhone(self, data):
        errorMessage = ""
        if "phone" in data:
            phone = data["phone"]
            if self.validatePhone(phone) == True:
                if self.checkPhoneIsNotExists(phone) == True:
                    return phone
                else:
                    errorMessage = "Phone is already registered"
            else:
                errorMessage = "Invalid Phone"
        else:
            errorMessage = "Phone is required"
        
        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})

    def checkIsTryingToBePregnant(self,data):
        errorMessage = ""
        isTryingToBePregnant = False
        if "isTryingToBePregnant" in data:
            isTryingToBePregnant = data["isTryingToBePregnant"]
        else:
            errorMessage = "isTryingToBePregnant key is required"
        
        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})
        
        return isTryingToBePregnant

    def checkPassword(self,data):
        if "password" in data:
            password = data["password"]
            if validatePassword(password) == True:
                return password
            else:
                errorMessage = "Password must consists of 6 digits only"
        else:
            errorMessage = "Password is required"
        
        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})


    def checkDueDateOrBirthday(self,data):
        errorMessage = ""
        dueDateOrBirthday = datetime.now()
        if "dueDateOrBirthday" in data:
            dueDateOrBirthday = data["dueDateOrBirthday"]
        else:
            errorMessage = "dueDateOrBirthday key is required"
        
        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})
        
        return dueDateOrBirthday
    
    def getGender(self,data):
        selectedGender = None
        genderList = Gender.objects.filter(keyName = "idk")
        
        if genderList.__len__() > 0:
            selectedGender = genderList[0]
        
        if selectedGender is None:
            raise serializers.ValidationError({"error": ["Gender is required"]})
        
        return selectedGender

    def checkLanguage(self,data):
        errorMessage = ""
        selectedLanguage = None
        languageList = Language.objects.filter(id = data["languageId"])
        if languageList.__len__() > 0:
            selectedLanguage = languageList[0]
            if selectedLanguage.isEnabled == False:
                errorMessage = "Language is not enabled"
        else:
            errorMessage = "languageId key is required"
        
        if len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})
        
        return selectedLanguage

    def create(self, validated_data):
        
        childTypeId = None

        selectedGender = self.getGender(validated_data)
        
        dueDateOrBirthday = self.checkDueDateOrBirthday(validated_data)

        isTryingToBePregnant = self.checkIsTryingToBePregnant(validated_data)

        if isTryingToBePregnant == False:
            dueDateOrBirthday = dueDateOrBirthday.date()
            today = datetime.now().date()
            childTypeList = []
            if dueDateOrBirthday > today:
                childTypeList = ChildType.objects.filter(keyName = "pregnant")
            else:
                childTypeList = ChildType.objects.filter(keyName = "child")
                
            if childTypeList.__len__() > 0:
                childTypeId = childTypeList[0]
            
        language = self.checkLanguage(validated_data)

        phone = self.checkPhone(validated_data)

        password = self.checkPassword(validated_data)

        isParentCreated = False
        isChildCreated = False
        isMedicalProfileCreated = False
        
        parent = Parent(
                phone = phone,
                password = password,
                languageId = language,
                createdDate = datetime.now(),
                updatedDate = datetime.now()
            )
        parent.save()
        if parent.id is not None:
            isParentCreated = True
            child = Child(
                    isTryingToBePregnant = isTryingToBePregnant,
                    dateOfBirth = dueDateOrBirthday,
                    childTypeId = childTypeId,
                    genderId = selectedGender,
                    isSelected = True,
                    createdDate = datetime.now(),
                    updatedDate = datetime.now(),
                    parentId = parent
                )
            child.save()
            if child.id is not None:
                isChildCreated = True
                medicalProfile = MedicalProfile(
                        childId = child,
                        createdDate = datetime.now(),
                        updatedDate = datetime.now()
                    )
                medicalProfile.save()
                if medicalProfile.childId is not None:
                    isMedicalProfileCreated = True

        
        return JsonResponse({
                "phone":phone,
                "password":password,
                "isTryingToBePregnant":isTryingToBePregnant,
                "dueDateOrBirthday":dueDateOrBirthday,
                languageKey:language.id,
                "isParentCreated":isParentCreated,
                "isChildCreated":isChildCreated,
                "isMedicalProfileCreated":isMedicalProfileCreated,
                "parent":ParentSerializer(parent).data
            })

# Parent

class ParentSerializer(serializers.ModelSerializer):
    parentDetail = serializers.SerializerMethodField()
    token = serializers.SerializerMethodField()
    subscriptionInfo = serializers.SerializerMethodField()
    financialAccount = serializers.SerializerMethodField()

    class Meta:
        model = Parent
        exclude = ["password"]

    def get_parentDetail(self, instance):
        isExists = ParentDetail.objects.filter(parentId=instance.id).exists()
        if isExists == True:
            selected = ParentDetail.objects.get(parentId=instance.id)
            return ParentDetailSerializer(selected).data
        return None

    def get_token(self, instance):
        tokenList = ParentToken.objects.filter(parentId=instance.id)
        if tokenList.__len__() > 0:
            return ParentTokenSerializer(tokenList[0]).data
        else:
            selectedList = TokenType.objects.filter(keyName="parent")
            if selectedList.__len__() > 0:
                parentTokenMap = {}
                parentTokenMap["token"] = generateToken(selectedList[0].tokenTypeLen)
                parentTokenMap["createdDate"] = datetime.now()
                parentTokenMap["updatedDate"] = datetime.now()
                parentTokenMap["tokenTypeId"] = selectedList[0].id
                parentTokenMap["parentId"] = instance.id
                parentTokenSerializer = ParentTokenSerializer(data=parentTokenMap)
                if parentTokenSerializer.is_valid():
                    parentTokenSerializer.save()
                    return parentTokenSerializer.data

        return None

    def get_subscriptionInfo(self, instance):
        return getSubscriptionInfo(self,instance)

    def get_financialAccount(self, instance):
        isExists = FinancialProfile.objects.filter(parentId=instance.id).exists()
        if isExists == True:
            selected = FinancialProfile.objects.get(parentId=instance.id)
            return FinancialProfileSerializer(selected).data
        else:
            finAccMap = {
                "createdDate": datetime.now(),
                "updatedDate": datetime.now(),
                "parentId": instance.id,
            }
            finAccSerializer = FinancialProfileSerializer(data=finAccMap)
            if finAccSerializer.is_valid():
                finAccSerializer.save()
                return finAccSerializer.data

# Parent Detail

class ParentDetailSerializer(serializers.ModelSerializer):
    class Meta:
        model = ParentDetail
        fields = [
            "parentId",
            "firstName",
            "lastName",
            "email",
            "createdDate",
            "updatedDate"
        ]

    def validate(self, data):
        errorMessage = ""
        isCheck = False
        if "parentId" in data:
            isCheck = validateParentId(self, data["parentId"].id)
        else:
            errorMessage = "Parent Id does not exit"

        if isCheck == True:
            return data

        elif len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})


# Parent Token

class ParentTokenSerializer(serializers.ModelSerializer):
    class Meta:
        model = ParentToken
        fields = ["parentId", "token", "createdDate", "updatedDate", "tokenTypeId"]

# Emergency Contact

class EmergencyContactSerializer(serializers.ModelSerializer):
    isAuthorized = serializers.SerializerMethodField()
    class Meta:
        model = EmergencyContact
        fields = [
            "id",
            "fullName",
            "phone",
            "createdDate",
            "updatedDate",
            "parentId",
            "isAuthorized",
        ]

    def get_isAuthorized(self,instance):
        return validateParentId(self,instance.parentId.id)

    def validate(self, data):
        errorMessage = ""
        isCheck = False
        if "parentId" in data:
            isCheck = validateParentId(self, data["parentId"].id)
        else:
            errorMessage = "Parent Id does not exit"

        if isCheck == True:
            return data

        elif len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})

# Child

class ChildSerializer(serializers.ModelSerializer):
    gender = serializers.SerializerMethodField()
    childType = serializers.SerializerMethodField()
    medicalProfile = serializers.SerializerMethodField()
    isAuthorized = serializers.SerializerMethodField()

    class Meta:
        model = Child
        fields = [
            "id",
            "isTryingToBePregnant",
            "isSelected",
            "name",
            "dateOfBirth",
            "weight",
            "length",
            "head",
            "createdDate",
            "updatedDate",
            "childTypeId",
            "genderId",
            "parentId",
            "childType",
            "gender",
            "medicalProfile",
            "isAuthorized",
        ]

    def get_isAuthorized(self,instance):
        return validateParentId(self,instance.parentId.id)

    def validate(self, data):
        isCheck = False
        if "parentId" in data:
            isCheck = validateParentId(self, data["parentId"].id)
        else:
            errorMessage = "Parent Id does not exit"

        if isCheck == True:
            return data

        elif len(errorMessage) > 0:
            raise serializers.ValidationError({"error": [errorMessage]})

    def get_childType(self, instance):
        languageId = getLanguage(self)
        if instance.childTypeId is not None:
            isExists = ChildType.objects.filter(id=instance.childTypeId.id).exists()
            if isExists == True:
                selectedChildType = ChildType.objects.get(id=instance.childTypeId.id)
                return ChildTypeSerializer(
                    selectedChildType, context={languageKey: languageId}
                ).data
        return None

    def get_gender(self, instance):
        languageId = getLanguage(self)
        if instance.genderId is not None:
            isExists = Gender.objects.filter(id=instance.genderId.id).exists()
            if isExists == True:
                selectedGender = Gender.objects.get(id=instance.genderId.id)
                return GenderSerializer(
                    selectedGender, context={languageKey: languageId}
                ).data
        return None

    def get_medicalProfile(self, instance):
        return getMedicalProfile(self,instance)


