import json
from django.db import models

from module_iam.models import BaseModel, IAmPrincipal


class FoodIngredintDataset(models.Model):
    food_name = models.CharField(max_length=100)
    ingredients = models.JSONField(default=list)

    class Meta:
        db_table = "food_ingredient_dataset"

    def set_ingredients(self, x):
        self.ingredients = json.dumps(x)

    def get_ingredients(self):
        return json.loads(self.ingredients)


class PrincipalHealthData(BaseModel):
    principal = models.OneToOneField(
        IAmPrincipal,
        on_delete=models.CASCADE,
        related_name="health_data_principal",
        verbose_name="Principal",
        db_index=True,
    )
    # Gastrointestinal health (choices if applicable)
    gastrointestinal_health = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="Gastrointestinal Health",
        help_text="Describe your gastrointestinal health (e.g., best, average, poor, etc.)",
    )

    # Exercise frequency (choices if applicable)
    exercise_frequency = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="Exercise Frequency",
        help_text="Describe your exercise frequency (e.g., Less than equal to 3 days, 2 days, Greater than 3 days, etc.)",
    )

    sleep_duration = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="Sleep Duration (hours)",
        help_text="Enter your average sleep duration in hours per night.",
    )

    # Ethnicity (choices if applicable)
    ethenicity = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="Ethnicity",
        help_text="Select your ethnicity.",
    )

    weight = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        default=0.0,
        blank=True,
        null=True,
        verbose_name="Weight",
        help_text="Enter your weight in kilograms.",
    )

    weight_unit = models.CharField(
        max_length=10,
        choices=[
            ('kg', 'kg'),
            ('lbs', 'lbs'),
        ],
        default="lbs",
        blank=True,
        null=True,
        verbose_name="Weight Unit",
        help_text="Select your weight unit.",
    )

    converted_weight_kg = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        blank=True,
        null=True,
        verbose_name="Converted Weight",
        help_text="The equivalent weight converted into kilograms.",
    )

    height = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        default=0.0,
        blank=True,
        null=True,
        verbose_name="Height",
        help_text="Enter your height in centimeters.",
    )

    height_unit = models.CharField(
        max_length=10,
        choices=[
            ('cm', 'cm'),
            ('ft+inch', 'ft+inch'),
        ],
        default='cm',
        blank=True,
        null=True,
        verbose_name="Height Unit",
        help_text="Select your height unit.",
    )

    converted_height_cm = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        blank=True,
        null=True,
        verbose_name="Converted Height",
        help_text="The equivalent height converted into centimeters.",
    )

    # Eat frequency (choices if applicable)
    eat_frequency = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        verbose_name="Eating Frequency",
        help_text="Describe your eating frequency (e.g., 3 meals per day, frequent snacking, etc.)",
    )

    class Meta:
        db_table = "princpal_health_data"

    def __str__(self):
        return f"Health Data for {self.principal}"
    
    @property
    def converted_height_in_cm(self):
        if self.height_unit == 'ft+inch':
            feet, inches = divmod(float(self.height) * 10, 12)
            return round(feet * 30.48 + inches * 2.54, 2)  # Convert feet to cm and inches to cm
        return None

    @property
    def converted_weight_in_kg(self):
        if self.weight_unit == 'lbs':
            return round(float(self.weight) * 0.453592, 2)  # Convert pounds to kg
        return None

    def save(self, *args, **kwargs):
        if self.height_unit == 'ft+inch':
            self.converted_height_cm = self.converted_height_in_cm  # Update converted height
        if self.weight_unit == 'lbs':
            self.converted_weight_kg = self.converted_weight_in_kg  # Update converted weight
        super().save(*args, **kwargs)


class Intolerance(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal,
        on_delete=models.CASCADE,
        related_name="intolerance_principal",
        db_index=True,
    )
    name = models.CharField(max_length=255, blank=True, null=True)
    duration = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        db_table = "intolerance"

    def __str__(self):
        return f"intolerance of {self.principal}"


class Symptoms(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal,
        on_delete=models.CASCADE,
        related_name="symptoms_principal",
        db_index=True,
    )
    name = models.CharField(max_length=255, blank=True, null=True)
    duration = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        db_table = "symptoms"

    def __str__(self):
        return f"symptoms of {self.principal}"


class PastTreatment(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal,
        on_delete=models.CASCADE,
        related_name="pasttreatment_principal",
        db_index=True,
    )
    name = models.CharField(max_length=255, blank=True, null=True)
    duration = models.DateField()
    is_recurring = models.BooleanField(default=False)
    treatment_frequency = models.TextField(blank=True, null=True)

    class Meta:
        db_table = "past_treatment"

    def __str__(self):
        return f"past treatment of {self.principal}"


class ChronicCondition(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal,
        on_delete=models.CASCADE,
        related_name="chronic_principal",
        db_index=True,
    )
    name = models.CharField(max_length=255, blank=True, null=True)
    duration = models.CharField(max_length=255, blank=True, null=True)

    class Meta:
        db_table = "chronic_condition"

    def __str__(self):
        return f"chronic condition of {self.principal}"


class FoodIngredientRecord(models.Model):
    name = models.CharField(max_length=100)
    from_dataset = models.BooleanField(default=False)

    class Meta:
        db_table = "food_ingredient_record"

class FoodRecord(models.Model):
    name = models.CharField(max_length=100)
    quantity = models.IntegerField()

    class Meta:
        db_table = "food_record"

class BeverageRecord(models.Model):
    beverage_type = models.CharField(max_length=100)
    quantity = models.IntegerField()
    quantity_measure = models.CharField(max_length=100)

    class Meta:
        db_table = "beverage_record"

class MealRecord(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal, related_name="meal_principal", on_delete=models.CASCADE
    )
    date = models.DateField()
    time = models.TimeField()
    meal_type = models.CharField(max_length=100, blank=True, null=True)
    food_records = models.ManyToManyField(FoodRecord, through='MealRecordFoodRecord')
    beverage_records = models.ManyToManyField(BeverageRecord, through='MealRecordBeverageRecord')
    food_ingredient_records = models.ManyToManyField(FoodIngredientRecord, through='MealRecordFoodIngredientRecord')

    class Meta:
        db_table = "meal_record"

class MealRecordFoodRecord(models.Model):
    meal_record = models.ForeignKey(MealRecord, on_delete=models.CASCADE)
    food_record = models.ForeignKey(FoodRecord, on_delete=models.CASCADE)

    class Meta:
        db_table = "meal_record_food_record"

class MealRecordBeverageRecord(models.Model):
    meal_record = models.ForeignKey(MealRecord, on_delete=models.CASCADE)
    beverage_record = models.ForeignKey(BeverageRecord, on_delete=models.CASCADE)

    class Meta:
        db_table = "meal_record_beverage_record"

class MealRecordFoodIngredientRecord(models.Model):
    meal_record = models.ForeignKey(MealRecord, on_delete=models.CASCADE)
    food_ingredient_record = models.ForeignKey(FoodIngredientRecord, on_delete=models.CASCADE)

    class Meta:
        db_table = "meal_record_food_ingredient_record"

class Medicine(models.Model):
    name = models.CharField(max_length=255, blank=True, null=True)
    quantity = models.IntegerField(default=0)
    type = models.CharField(max_length=100, blank=True, null=True)

    class Meta:
        db_table = "medicine"

    def __str__(self):
        return f"{self.name} Medicine"

class Medication(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal, related_name="medication_principal", on_delete=models.CASCADE
    )
    date = models.DateField()
    time = models.TimeField()
    medicines = models.ManyToManyField(
        Medicine,
        through="MedicationMedicine",
        related_name="medications"
    )

    class Meta:
        db_table = "medication"

class MedicationMedicine(models.Model):
    medication = models.ForeignKey(Medication, related_name="medication_medicines", on_delete=models.CASCADE)
    medicine = models.ForeignKey(Medicine, related_name="medication_medicines", on_delete=models.CASCADE)

    class Meta:
        db_table = "medication_medicine"


class Bowel(BaseModel):
    principal = models.ForeignKey(
        IAmPrincipal, related_name="bowel_principal", on_delete=models.CASCADE
    )
    date = models.DateField()
    time = models.TimeField()
    stool_type = models.CharField(max_length=100, blank=True, null=True)
    stool_name = models.CharField(max_length=100, blank=True, null=True)
    duration = models.DurationField(blank=True, null=True)
    completeness_of_evacuation = models.CharField(max_length=100, blank=True, null=True)
    urgency = models.CharField(max_length=100, blank=True, null=True)
    smellness = models.CharField(max_length=100, blank=True, null=True)
    pain_level = models.CharField(max_length=100, blank=True, null=True)
    volume = models.CharField(max_length=100, blank=True, null=True)
    color = models.CharField(max_length=100, blank=True, null=True)
    excessive_flatulence = models.BooleanField(default=False)

    class Meta:
        db_table = "bowel"


class SymptomTypeBeforeMeal(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        db_table = "symptom_type_before_meal"

class SymptomTypeAfterMeal(models.Model):
    name = models.CharField(max_length=100)

    class Meta:
        db_table = "symptom_type_after_meal"

class MealSymptomRecord(BaseModel):
    principal = models.ForeignKey(IAmPrincipal, related_name="meal_symptom_principal", on_delete=models.CASCADE)
    related_meal = models.ForeignKey(MealRecord, related_name="symptom_related_meal", on_delete=models.SET_NULL, null=True)
    date = models.DateField()
    time = models.TimeField()
    symptoms_description = models.TextField(blank=True, null=True)
    interval = models.DurationField()
    symptoms_before_meal = models.ManyToManyField(SymptomTypeBeforeMeal, through='SymptomRecordBeforeMeal')
    symptoms_after_meal = models.ManyToManyField(SymptomTypeAfterMeal, through='SymptomRecordAfterMeal')

    class Meta:
        db_table = "meal_symptom_record"

class SymptomRecordBeforeMeal(models.Model):
    symptom_record = models.ForeignKey(MealSymptomRecord, on_delete=models.CASCADE)
    symptom_type_before_meal = models.ForeignKey(SymptomTypeBeforeMeal, on_delete=models.CASCADE)

    class Meta:
        db_table = "symptom_record_before_meal"

class SymptomRecordAfterMeal(models.Model):
    symptom_record = models.ForeignKey(MealSymptomRecord, on_delete=models.CASCADE)
    symptom_type_after_meal = models.ForeignKey(SymptomTypeAfterMeal, on_delete=models.CASCADE)

    class Meta:
        db_table = "symptom_record_after_meal"