import math
import os
from datetime import datetime

from django.conf import settings
from django.utils import timezone
from rest_framework import serializers

from module_iam.models import IAmPrincipal

from ..models import (
    BeverageRecord,
    Bowel,
    ChronicCondition,
    FoodIngredientRecord,
    FoodIngredintDataset,
    FoodRecord,
    Intolerance,
    MealRecord,
    MealSymptomRecord,
    Medication,
    Medicine,
    PastTreatment,
    PrincipalHealthData,
    Symptoms,
    SymptomTypeAfterMeal,
    SymptomTypeBeforeMeal,
)

class FoodDatasetSerializer(serializers.ModelSerializer):
    class Meta:
        model = FoodIngredintDataset
        fields = ["id", "food_name"]

class FoodIngredientDatasetSerializer(serializers.ModelSerializer):
    class Meta:
        model = FoodIngredintDataset
        fields = ['id', 'food_name', 'ingredients']


class IAmPrincipalSerializer(serializers.ModelSerializer):
    class Meta:
        model = IAmPrincipal
        fields = [
            "profile_photo",
            "first_name",
            "date_of_birth",
            "gender",
            "phone_no",
        ]


class PrincipalHealthDataSerializer(serializers.ModelSerializer):
    weight = serializers.DecimalField(max_digits=5, decimal_places=2, read_only=True)
    height = serializers.DecimalField(max_digits=6, decimal_places=2, read_only=True)

    class Meta:
        model = PrincipalHealthData
        fields = [
            "ethenicity",
            "weight",
            "weight_unit",
            "height",
            "height_unit",
            "gastrointestinal_health",
            "exercise_frequency",
            "sleep_duration",
            "eat_frequency",
        ]


class PrincipalAndHealthSerializer(serializers.ModelSerializer):
    ethenicity = serializers.CharField(read_only=True)
    weight = serializers.DecimalField(max_digits=5, decimal_places=2, read_only=True)
    weight_unit = serializers.CharField(max_length=10, read_only=True)
    height = serializers.DecimalField(max_digits=6, decimal_places=2, read_only=True)
    height_unit = serializers.CharField(max_length=10, read_only=True)
    gastrointestinal_health = serializers.CharField(read_only=True)
    exercise_frequency = serializers.CharField(read_only=True)
    sleep_duration = serializers.CharField(read_only=True)
    eat_frequency = serializers.CharField(read_only=True)
    profile_complete = serializers.IntegerField(read_only=True)

    class Meta:
        model = IAmPrincipal
        fields = [
            "profile_photo",
            "first_name",
            "email",
            "date_of_birth",
            "gender",
            "phone_no",
            # "phone_verified",
            # "email_verified",
            "ethenicity",
            "weight",
            "weight_unit",
            "height",
            "height_unit",
            "gastrointestinal_health",
            "exercise_frequency",
            "sleep_duration",
            "eat_frequency",
            "profile_complete",
        ]

    def calculate_profile_completion(self, user):
        """
        Calculates the profile completion percentage for a user based on the required fields.
        """
        fields = [
            "profile_photo",
            "first_name",
            "email",
            "date_of_birth",
            "gender",
            "phone_no",
            "ethenicity",
            "weight",
            "height",
            "gastrointestinal_health",
            "exercise_frequency",
            "sleep_duration",
            "eat_frequency",
        ]
        try:
            # Retrieve the user profile from the database
            profile = IAmPrincipal.objects.get(id=user)
            try:
                # Retrieve the user's health data from the database
                health_data = PrincipalHealthData.objects.get(principal=profile)
            except PrincipalHealthData.DoesNotExist:
                # If health data doesn't exist, set health_data to None
                health_data = None

            # Initialize a counter for completed fields
            completed_fields = sum(
                1
                for field in fields
                if (
                    # If the field is in the user profile and the field value is not None, not an empty string, and not an instance of datetime.date
                    (
                        field in vars(profile)
                        and vars(profile).get(field, "")
                        and vars(profile).get(field) != datetime.date
                    )
                    or
                    # If health data exists, the field is in the user's health data, and the field value is not None, not an empty string, and not an instance of datetime.date
                    (
                        health_data
                        and field in vars(health_data)
                        and vars(health_data).get(field, "")
                        and vars(health_data).get(field) != datetime.date
                    )
                )
            )

        except IAmPrincipal.DoesNotExist:
            # If the user profile doesn't exist, return 0
            return 0

        # Calculate the total number of fields
        total_fields = len(fields)

        # Calculate the profile completion percentage
        completion_percentage = math.floor((completed_fields / total_fields) * 100)

        # Return the profile completion percentage
        return completion_percentage

    def get_image_url(self, obj, field_name, request):
        image_field = getattr(obj, field_name)
        if image_field:
            return request.build_absolute_uri(image_field.url)
        else:
            # Return the URL of the default image from the static path
            default_image_path = os.path.join(
                settings.STATIC_URL, "img/default_profile.jpg"
            )
            return request.build_absolute_uri(default_image_path)

    def to_representation(self, instance):
        data = super().to_representation(instance)
        request = self.context.get("request")
        data["profile_photo"] = self.get_image_url(instance, "profile_photo", request)
        data["profile_complete"] = self.calculate_profile_completion(request.user.id)
        if (
            hasattr(instance, "health_data_principal")
            and instance.health_data_principal
        ):
            health_data = instance.health_data_principal
            data["ethenicity"] = health_data.ethenicity
            data["weight"] = health_data.weight
            data["weight_unit"] = health_data.weight_unit
            data["height"] = health_data.height
            data["height_unit"] = health_data.height_unit
            data["gastrointestinal_health"] = health_data.gastrointestinal_health
            data["exercise_frequency"] = health_data.exercise_frequency
            data["sleep_duration"] = health_data.sleep_duration
            data["eat_frequency"] = health_data.eat_frequency
        else:
            # If health_data_principal doesn't exist or is empty, set empty strings for all attributes
            data["ethenicity"] = ""
            data["weight"] = 0.00
            data["weight_unit"] = "kg"
            data["height"] = 0.00
            data["height_unit"] = "cm"
            data["gastrointestinal_health"] = ""
            data["exercise_frequency"] = ""
            data["sleep_duration"] = ""
            data["eat_frequency"] = ""
        return data


class IntoleranceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Intolerance
        fields = ["id", "name", "duration"]


class SymptomsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Symptoms
        fields = ["id", "name", "duration"]


class PastTreatmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = PastTreatment
        fields = ["id", "name", "duration", "is_recurring", "treatment_frequency"]


class ChronicConditionSerializer(serializers.ModelSerializer):
    class Meta:
        model = ChronicCondition
        fields = ["id", "name", "duration"]


class FoodIngredientRecordSerializer(serializers.ModelSerializer):
    class Meta:
        model = FoodIngredientRecord
        fields = ["name", "from_dataset"]


class FoodRecordSerializer(serializers.ModelSerializer):
    class Meta:
        model = FoodRecord
        fields = ["name", "quantity"]


class BeverageRecordSerializer(serializers.ModelSerializer):
    class Meta:
        model = BeverageRecord
        fields = [
            "beverage_type",
            "quantity",
            "quantity_measure",
        ]


class MealRecordSerializer(serializers.ModelSerializer):
    food_records = FoodRecordSerializer(many=True)
    beverage_records = BeverageRecordSerializer(many=True)
    food_ingredient_records = FoodIngredientRecordSerializer(many=True)

    class Meta:
        model = MealRecord
        fields = [
            "id",
            "date",
            "time",
            "meal_type",
            "food_records",
            "food_ingredient_records",
            "beverage_records",
        ]

    def create(self, validated_data):
        food_record_data = validated_data.pop("food_records", [])
        beverage_record_data = validated_data.pop("beverage_records", [])
        food_ingredient_record_data = validated_data.pop("food_ingredient_records", [])

        meal_record = self.Meta.model.objects.create(**validated_data)
        print(f"meal recordd id in serializer {meal_record.id}")
        food_record_list = []
        for data in food_record_data:
            obj, _ = FoodRecord.objects.get_or_create(**data)
            food_record_list.append(obj)

        food_ingredient_list = []
        for data in food_ingredient_record_data:
            obj, _ = FoodIngredientRecord.objects.get_or_create(**data)
            food_ingredient_list.append(obj)

        beverage_record_list = []
        for data in beverage_record_data:
            obj, _ = BeverageRecord.objects.get_or_create(**data)
            beverage_record_list.append(obj)

        meal_record.food_records.set(food_record_list)
        meal_record.food_ingredient_records.set(food_ingredient_list)
        meal_record.beverage_records.set(beverage_record_list)

        return meal_record

    def update(self, instance, validated_data):
        instance.date = validated_data.get("date", instance.date)
        instance.time = validated_data.get("time", instance.time)
        instance.meal_type = validated_data.get("meal_type", instance.meal_type)
        instance.save()

        print(f"meal record id in  update 1 method {instance.id}")

        food_record_data = validated_data.pop("food_records", [])
        beverage_record_data = validated_data.pop("beverage_records", [])
        food_ingredient_record_data = validated_data.pop("food_ingredient_records", [])

        food_record_list = []
        for data in food_record_data:
            obj, _ = FoodRecord.objects.get_or_create(**data)
            food_record_list.append(obj)

        food_ingredient_list = []
        for data in food_ingredient_record_data:
            obj, _ = FoodIngredientRecord.objects.get_or_create(**data)
            food_ingredient_list.append(obj)

        beverage_record_list = []
        for data in beverage_record_data:
            obj, _ = BeverageRecord.objects.get_or_create(**data)
            beverage_record_list.append(obj)

        instance.food_records.set(food_record_list)
        instance.food_ingredient_records.set(food_ingredient_list)
        instance.beverage_records.set(beverage_record_list)

        instance.save()
        print(f"meal record id in  update 2 method {instance.id}")
        return instance


class MedicineSerializer(serializers.ModelSerializer):
    class Meta:
        model = Medicine
        fields = ["name", "quantity", "type"]


class MedicationSerializer(serializers.ModelSerializer):
    medicines = MedicineSerializer(many=True)

    class Meta:
        model = Medication
        fields = ["id", "date", "time", "medicines"]

    def create(self, validated_data):
        medicines_data = validated_data.pop("medicines")
        medication = self.Meta.model.objects.create(**validated_data)
        for medicine_data in medicines_data:
            medicine = Medicine.objects.create(**medicine_data)
            medication.medicines.add(medicine)
        return medication

    def update(self, instance, validated_data):
        instance.date = validated_data.get("date", instance.date)
        instance.time = validated_data.get("time", instance.time)
        instance.save()

        medicines_data = validated_data.get("medicines", [])
        instance.medicines.clear()
        for medicine_data in medicines_data:
            medicine = Medicine.objects.create(**medicine_data)
            instance.medicines.add(medicine)

        return instance


class BowelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bowel
        fields = [
            "id",
            "date",
            "time",
            "stool_type",
            "stool_name",
            "duration",
            "completeness_of_evacuation",
            "urgency",
            "smellness",
            "pain_level",
            "volume",
            "color",
            "excessive_flatulence",
        ]


class MealRecordSymptomsSerializer(serializers.ModelSerializer):

    class Meta:
        model = MealRecord
        fields = [
            "id",
            "date",
            "time",
            "meal_type",
        ]


class SymptomTypeBeforeMealSerializer(serializers.ModelSerializer):
    class Meta:
        model = SymptomTypeBeforeMeal
        fields = ["name"]


class SymptomTypeAfterMealSerializer(serializers.ModelSerializer):
    class Meta:
        model = SymptomTypeAfterMeal
        fields = ["name"]


class MealSymptomRecordSerializer(serializers.ModelSerializer):
    symptoms_before_meal = SymptomTypeBeforeMealSerializer(many=True)
    symptoms_after_meal = SymptomTypeAfterMealSerializer(many=True)
    related_meal_id = serializers.PrimaryKeyRelatedField(
        queryset=MealRecord.objects.all(), write_only=True
    )  # Added field to accept meal ID
    related_meal = MealRecordSymptomsSerializer(read_only=True)

    class Meta:
        model = MealSymptomRecord
        fields = [
            "id",
            "date",
            "time",
            "symptoms_description",
            "interval",
            "symptoms_before_meal",
            "symptoms_after_meal",
            "related_meal_id",
            "related_meal"
        ]

    def create(self, validated_data):
        before_meal_data = validated_data.pop("symptoms_before_meal")
        after_meal_data = validated_data.pop("symptoms_after_meal")
        related_meal_id = validated_data.pop("related_meal_id")

        meal_symptom_record = MealSymptomRecord.objects.create(
            related_meal=related_meal_id, **validated_data
        )

        print(f"symptoms meal record  in create {meal_symptom_record.id, meal_symptom_record.related_meal.id}")

        before_meal_list = []
        for data in before_meal_data:
            obj, _ = SymptomTypeBeforeMeal.objects.get_or_create(**data)
            before_meal_list.append(obj)

        after_meal_list = []
        for data in after_meal_data:
            obj, _ = SymptomTypeAfterMeal.objects.get_or_create(**data)
            after_meal_list.append(obj)

        meal_symptom_record.symptoms_before_meal.set(before_meal_list)
        meal_symptom_record.symptoms_after_meal.set(after_meal_list)

        return meal_symptom_record

    def update(self, instance, validated_data):
        instance.date = validated_data.get("date", instance.date)
        instance.time = validated_data.get("time", instance.time)
        instance.symptoms_description = validated_data.get(
            "symptoms_description", instance.symptoms_description
        )
        instance.interval = validated_data.get("interval", instance.interval)

        related_meal_id = validated_data.pop("related_meal_id", None)  # Extract meal ID
        if related_meal_id is not None:
            instance.related_meal = related_meal_id

        before_meal_data = validated_data.pop("symptoms_before_meal", [])
        after_meal_data = validated_data.pop("symptoms_after_meal", [])

        before_meal_instances = []
        for data in before_meal_data:
            obj, _ = SymptomTypeBeforeMeal.objects.get_or_create(**data)
            before_meal_instances.append(obj)

        after_meal_instances = []
        for data in after_meal_data:
            obj, _ = SymptomTypeAfterMeal.objects.get_or_create(**data)
            after_meal_instances.append(obj)

        instance.symptoms_before_meal.set(before_meal_instances)
        instance.symptoms_after_meal.set(after_meal_instances)

        instance.save()
        print(f"symptoms meal record  in update {instance.id, instance.related_meal.id}")

        return instance
