# all relation table if need customize, will put in this file
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models

from backend import settings

class TtStaffAvoidConcurrency(models.Model):
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE,related_name="avoid_concurrency_from")
    avoid_staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE,related_name="avoid_concurrency_to")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_staff_avoid_concurrency"  # custom table name
        unique_together = ("staff", "avoid_staff")  # prevent duplicates

    # when calling .add, will auto run this function
    # when insert staff a avoid staff b, automatic insert staff b avoid staff a also
    # not using this code, cause will run extra query
    # def save(self, *args, **kwargs):
    #     super().save(*args, **kwargs)
    #
    #     # prevent infinite recursion
    #     if not TtStaffAvoidConcurrency.objects.filter(
    #         staff=self.avoid_staff,
    #         avoid_staff=self.staff
    #     ).exists():
    #         TtStaffAvoidConcurrency.objects.create(
    #             staff=self.avoid_staff,
    #             avoid_staff=self.staff
    #         )

class TtLocationAvoidConcurrency(models.Model):
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE,related_name="avoid_concurrency_from")
    avoid_location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE,related_name="avoid_concurrency_to")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_location_avoid_concurrency"  # custom table name
        unique_together = ("location", "avoid_location")  # prevent duplicates

    # when calling .add, will auto run this function
    # when insert location a avoid location b, automatic insert location b avoid location a also
    def save(self, *args, **kwargs):
        """Enforce symmetry: if A avoids B, auto-create B avoids A."""
        super().save(*args, **kwargs)

        # prevent infinite recursion
        if not TtLocationAvoidConcurrency.objects.filter(
            location=self.avoid_location,
            avoid_location=self.location
        ).exists():
            TtLocationAvoidConcurrency.objects.create(
                location=self.avoid_location,
                avoid_location=self.location
            )

class TtStaffSuitability(models.Model):
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    suitability = models.ForeignKey("api.TtSuitability",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_staff_suitability"  # custom table name
        unique_together = ("staff", "suitability")  # prevent duplicates

class TtLocationSuitability(models.Model):
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    suitability = models.ForeignKey("api.TtSuitability",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_location_suitability"  # custom table name
        unique_together = ("location", "suitability")  # prevent duplicates

class TtStaffConstraintProfile(models.Model):
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_staff_constraint_profile"  # custom table name
        unique_together = ("staff", "constraint_profile")  # prevent duplicates

class TtLocationConstraintProfile(models.Model):
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_location_constraint_profile"  # custom table name
        unique_together = ("location", "constraint_profile")  # prevent duplicates

class TtStaffSharedWithDepartment(models.Model):
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    department = models.ForeignKey("api.TtDepartment",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_staff_shared_with_department"  # custom table name
        unique_together = ("staff", "department")  # prevent duplicates

class TtLocationSharedWithDepartment(models.Model):
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    department = models.ForeignKey("api.TtDepartment",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_location_shared_with_department"  # custom table name
        unique_together = ("location", "department")  # prevent duplicates

class TtAcademicTermWeek(models.Model):
    academic_term = models.ForeignKey("api.TtAcademicTerm",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_academic_term_week"  # custom table name
        unique_together = ("academic_term", "week")  # prevent duplicates

class TtWeekPatternWeek(models.Model):
    week_pattern = models.ForeignKey("api.TtWeekPattern",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_week_pattern_week"  # custom table name
        unique_together = ("week_pattern", "week")  # prevent duplicates

class UserRole(models.Model):
    id = models.BigAutoField(primary_key=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    role = models.ForeignKey("api.role", on_delete=models.CASCADE)

    class Meta:
        db_table = "user_role"
        constraints = [
            models.UniqueConstraint(fields=["user", "role"], name="unique_user_role")
        ]

class TtPosModuleGroup(models.Model):
    code = models.CharField(max_length=150)# used for import data can find pos module group module
    pos = models.ForeignKey("api.TtPos",on_delete=models.CASCADE)
    module_group = models.ForeignKey("api.TtModuleGroup",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    module = models.ManyToManyField("api.TtModule",through="api.TtPosModuleGroupModule")
    class Meta:
        db_table = "tt_pos_module_group"  # custom table name
        unique_together = ("pos", "module_group")  # prevent duplicates

class TtPosModuleGroupModule(models.Model):
    pos_module_group = models.ForeignKey("api.TtPosModuleGroup",on_delete=models.CASCADE)
    module = models.ForeignKey("api.TtModule",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_pos_module_group_module"  # custom table name
        unique_together = ("pos_module_group", "module")  # prevent duplicates

class TtModuleWeek(models.Model):
    module = models.ForeignKey("api.TtModule",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_module_week"  # custom table name
        unique_together = ("module", "week")  # prevent duplicates

class TtStudentSetModule(models.Model):
    """
    This is link to pos_module_group_module table, not module table, just because name too long only make it become tt_student_set_module
    """
    student_set = models.ForeignKey("api.TtStudentSet",on_delete=models.CASCADE)
    module = models.ForeignKey("api.TtModule",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_set_module"  # custom table name
        unique_together = ("student_set", "module")  # prevent duplicates

class TtStudentSetConstraintProfile(models.Model):
    student_set = models.ForeignKey("api.TtStudentSet",on_delete=models.CASCADE)
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_set_constraint_profile"  # custom table name
        unique_together = ("student_set", "constraint_profile")  # prevent duplicates

class TtActivityTemplateStaff(models.Model):
    activity_template = models.ForeignKey("api.TtActivityTemplate",on_delete=models.CASCADE)
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_template_code": ["required", "string"],
        "staff_code": ["required", "string"]
    }

    class Meta:
        db_table = "tt_activity_template_staff"  # custom table name
        unique_together = ("activity_template", "staff")  # prevent duplicates

class TtActivityTemplateStaffSuitability(models.Model):
    activity_template = models.ForeignKey("api.TtActivityTemplate",on_delete=models.CASCADE)
    suitability = models.ForeignKey("api.TtSuitability",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_template_code": ["required", "string"],
        "suitability_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_template_staff_suitability"  # custom table name
        unique_together = ("activity_template", "suitability")  # prevent duplicates

class TtActivityTemplateLocation(models.Model):
    activity_template = models.ForeignKey("api.TtActivityTemplate",on_delete=models.CASCADE)
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_template_code": ["required", "string"],
        "location_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_template_location"  # custom table name
        unique_together = ("activity_template", "location")  # prevent duplicates

class TtActivityTemplateLocationSuitability(models.Model):
    activity_template = models.ForeignKey("api.TtActivityTemplate",on_delete=models.CASCADE)
    suitability = models.ForeignKey("api.TtSuitability",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_template_code": ["required", "string"],
        "suitability_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_template_location_suitability"  # custom table name
        unique_together = ("activity_template", "suitability")  # prevent duplicates

class TtActivityWeek(models.Model):
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_activity_week"  # custom table name
        unique_together = ("activity", "week")  # prevent duplicates

class TtActivityTemplateWeek(models.Model):
    activity_template = models.ForeignKey("api.TtActivityTemplate",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_activity_template_week"  # custom table name
        unique_together = ("activity_template", "week")  # prevent duplicates

class TtPathwayPosModuleGroupModule(models.Model):
    """
    DO NOT COPY THIS FUNCTION AS REFERENCE, SOME COLUMN IS ALLOW NULL FOR DO SOME CHECKING
    """
    pos_module_group_module = models.ForeignKey("api.TtPosModuleGroupModule",on_delete=models.SET_NULL,null=True)
    pathway = models.ForeignKey("api.TtPathway",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_pathway_pos_module_group_module"  # custom table name
        unique_together = ("pos_module_group_module", "pathway")  # prevent duplicates

class TtStudentSetActivity(models.Model):
    student_set = models.ForeignKey("api.TtStudentSet",on_delete=models.CASCADE)
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_set_activity"  # custom table name
        unique_together = ("student_set","activity")  # prevent duplicates

class TtStaffResourceMap(models.Model):
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    pattern = models.TextField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_staff_resource_map"  # custom table name
        unique_together = ("staff", "week")  # prevent duplicates

class TtLocationResourceMap(models.Model):
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    pattern = models.TextField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_location_resource_map"  # custom table name
        unique_together = ("location", "week")  # prevent duplicates

class TtStudentSetResourceMap(models.Model):
    student_set = models.ForeignKey("api.TtStudentSet",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    pattern = models.TextField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_set_resource_map"  # custom table name
        unique_together = ("student_set", "week")  # prevent duplicates

class TtStudentResourceMap(models.Model):
    student = models.ForeignKey("api.TtStudent",on_delete=models.CASCADE)
    week = models.ForeignKey("api.TtWeek",on_delete=models.CASCADE)
    pattern = models.TextField(null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_resource_map"  # custom table name
        unique_together = ("student", "week")  # prevent duplicates

class TtActivityStaff(models.Model):
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_activity_staff"  # custom table name
        unique_together = ("staff", "activity")  # prevent duplicates

class TtActivityLocation(models.Model):
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_activity_location"  # custom table name
        unique_together = ("location", "activity")  # prevent duplicates

class TtActivityStaffPreset(models.Model):
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    staff = models.ForeignKey("api.TtStaff",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_code": ["required", "string"],
        "staff_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_staff_preset"  # custom table name
        unique_together = ("activity", "staff")  # prevent duplicates

class TtActivityStaffSuitability(models.Model):
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    suitability = models.ForeignKey("api.TtSuitability",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_code": ["required", "string"],
        "suitability_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_staff_suitability"  # custom table name
        unique_together = ("activity", "suitability")  # prevent duplicates

class TtActivityLocationPreset(models.Model):
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    location = models.ForeignKey("api.TtLocation",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_code": ["required", "string"],
        "location_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_location_preset"  # custom table name
        unique_together = ("activity", "location")  # prevent duplicates

class TtActivityLocationSuitability(models.Model):
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE)
    suitability = models.ForeignKey("api.TtSuitability",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    IMPORT_RULES = {
        "activity_code": ["required", "string"],
        "suitability_code": ["required", "string"]
    }
    class Meta:
        db_table = "tt_activity_location_suitability"  # custom table name
        unique_together = ("activity", "suitability")  # prevent duplicates

class TtResourceBreakTimeBlock(models.Model):
    resource_break = models.ForeignKey("api.TtResourceBreak",on_delete=models.CASCADE)
    time_block = models.ForeignKey("api.TtTimeBlock",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_resource_break_time_block"  # custom table name
        unique_together = ("resource_break", "time_block")  # prevent duplicates

class TtFreeBlockTimeBlock(models.Model):
    free_block = models.ForeignKey("api.TtFreeBlock",on_delete=models.CASCADE)
    time_block = models.ForeignKey("api.TtTimeBlock",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_free_block_time_block"  # custom table name
        unique_together = ("free_block", "time_block")  # prevent duplicates

class TtMaximumHourTimeBlock(models.Model):
    maximum_hour = models.ForeignKey("api.TtMaximumHour",on_delete=models.CASCADE)
    time_block = models.ForeignKey("api.TtTimeBlock",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_maximum_hour_time_block"  # custom table name
        unique_together = ("maximum_hour", "time_block")  # prevent duplicates

class TtMaximumWorkspanTimeBlock(models.Model):
    maximum_workspan = models.ForeignKey("api.TtMaximumWorkspan",on_delete=models.CASCADE)
    time_block = models.ForeignKey("api.TtTimeBlock",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_maximum_workspan_time_block"  # custom table name
        unique_together = ("maximum_workspan", "time_block")  # prevent duplicates

class TtConstraintProfileResourceBreak(models.Model):
    resource_break = models.ForeignKey("api.TtResourceBreak",on_delete=models.CASCADE)
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_constraint_profile_resource_break"  # custom table name
        unique_together = ("resource_break", "constraint_profile")  # prevent duplicates

class TtConstraintProfileFreeBlock(models.Model):
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    free_block = models.ForeignKey("api.TtFreeBlock",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_constraint_profile_free_block"  # custom table name
        unique_together = ("free_block", "constraint_profile")  # prevent duplicates

class TtConstraintProfileMaximumHour(models.Model):
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    maximum_hour = models.ForeignKey("api.TtMaximumHour",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_constraint_profile_maximum_hour"  # custom table name
        unique_together = ("maximum_hour", "constraint_profile")  # prevent duplicates

class TtConstraintProfileMaximumWorkspan(models.Model):
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    maximum_workspan = models.ForeignKey("api.TtMaximumWorkspan",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_constraint_profile_maximum_workspan"  # custom table name
        unique_together = ("maximum_workspan", "constraint_profile")  # prevent duplicates

class TtConstraintProfileTravelTable(models.Model):
    constraint_profile = models.ForeignKey("api.TtConstraintProfile",on_delete=models.CASCADE)
    travel_table = models.ForeignKey("api.TtTravelTable",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_constraint_profile_travel_table"  # custom table name
        unique_together = ("travel_table", "constraint_profile")  # prevent duplicates

class TtActivitySequencing(models.Model):
    activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE,related_name="sequencing_from")
    sequencing_activity = models.ForeignKey("api.TtActivity",on_delete=models.CASCADE,related_name="sequencing_to")
    type = models.SmallIntegerField(null=True,db_comment="1 - same_time, 2 - preceding, 3 - succeeding")
    created_at = models.DateTimeField(auto_now_add=True)

    TYPE_TO_CODE = {
        "same_time": 1,
        "preceding": 2,
        "succeeding": 3,
    }
    class Meta:
        db_table = "tt_activity_sequencing"  # custom table name
        unique_together = ("activity", "sequencing_activity")  # prevent duplicates

class TtStudentAcademicTerm(models.Model):
    student = models.ForeignKey("api.TtStudent",on_delete=models.CASCADE)
    academic_term = models.ForeignKey("api.TtAcademicTerm",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_academic_term"  # custom table name
        unique_together = ("student","academic_term")  # prevent duplicates

class TtStudentPos(models.Model):
    student = models.ForeignKey("api.TtStudent",on_delete=models.CASCADE)
    pos = models.ForeignKey("api.TtPos",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_pos"  # custom table name
        unique_together = ("student","pos")  # prevent duplicates

class TtStudentPosModule(models.Model):
    """
    This is link to TtPosModuleGroupModule
    """
    student = models.ForeignKey("api.TtStudent",on_delete=models.CASCADE)
    pos_module_group_module = models.ForeignKey("api.TtPosModuleGroupModule",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_pos_module"  # custom table name
        unique_together = ("student","pos_module_group_module")  # prevent duplicates

class TtStudentSetStudent(models.Model):
    student_set = models.ForeignKey("api.TtStudentSet",on_delete=models.CASCADE)
    student = models.ForeignKey("api.TtStudent",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_set_student"  # custom table name
        unique_together = ("student_set","student")  # prevent duplicates

class TtStudentPathway(models.Model):
    student = models.ForeignKey("api.TtStudent",on_delete=models.CASCADE)
    pathway = models.ForeignKey("api.TtPathway",on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "tt_student_pathway"  # custom table name
        unique_together = ("student","pathway")  # prevent duplicates
