from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from .utils.file_upload_paths import subject_book_upload_path


class Standard(models.Model):

    STANDARD_TYPES = [
        ("nursery", "Nursery"),
        ("kg", "KG"),
        ("primary", "Primary"),
        ("secondary", "Secondary"),
        ("higher_secondary", "Higher Secondary"),
    ]

    name = models.CharField(max_length=100, unique=True)
    code = models.CharField(max_length=20, unique=True)
    order = models.PositiveIntegerField(unique=True)

    standard_type = models.CharField(max_length=20, choices=STANDARD_TYPES)

    description = models.TextField(blank=True)

    min_age = models.PositiveIntegerField(null=True, blank=True)
    max_age = models.PositiveIntegerField(null=True, blank=True)

    min_subjects = models.PositiveIntegerField(default=5)
    max_subjects = models.PositiveIntegerField(default=10)

    passing_percentage = models.DecimalField(max_digits=5, decimal_places=2, default=35)

    tuition_fee = models.DecimalField(
        max_digits=10, decimal_places=2, null=True, blank=True
    )

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return f"{self.name} ({self.code})"


class Section(models.Model):

    name = models.CharField(max_length=100)
    code = models.CharField(max_length=10, unique=True)

    description = models.TextField(blank=True)

    capacity = models.PositiveIntegerField(
        default=40, validators=[MinValueValidator(1), MaxValueValidator(100)]
    )

    section_type = models.CharField(
        max_length=20,
        choices=[
            ("REGULAR", "Regular"),
            ("SPECIAL_NEEDS", "Special Needs"),
            ("HONORS", "Honors"),
            ("GIFTED", "Gifted"),
            ("ATHLETIC", "Athletic"),
        ],
        null=True,
        blank=True,
    )

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.code


# =====================================================
# ACADEMIC YEAR
# =====================================================


class AcademicYear(models.Model):

    name = models.CharField(max_length=20, unique=True)
    code = models.CharField(max_length=10, unique=True, null=True, blank=True)

    start_date = models.DateField()
    end_date = models.DateField()

    terms_count = models.PositiveIntegerField(
        default=2, validators=[MinValueValidator(1), MaxValueValidator(4)]
    )

    fee_due_date = models.DateField(null=True, blank=True)

    is_active = models.BooleanField(default=False)
    is_frozen = models.BooleanField(default=False)
    admissions_open = models.BooleanField(default=False)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name


# =====================================================
# ACADEMIC TERM
# =====================================================


class AcademicTerm(models.Model):

    academic_year = models.ForeignKey(
        AcademicYear, on_delete=models.CASCADE, related_name="terms"
    )

    name = models.CharField(max_length=100)
    code = models.CharField(max_length=20)

    order = models.PositiveIntegerField()

    start_date = models.DateField()
    end_date = models.DateField()

    is_exam_term = models.BooleanField(default=False)

    weightage = models.DecimalField(max_digits=5, decimal_places=2, default=100.00)

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = (
            ("academic_year", "code"),
            ("academic_year", "order"),
        )

    def __str__(self):
        return f"{self.name} - {self.academic_year}"


# =====================================================
# SUBJECT CATEGORY
# =====================================================


class SubjectCategory(models.Model):

    name = models.CharField(max_length=50, unique=True)
    code = models.CharField(max_length=20, unique=True)

    def __str__(self):
        return self.name


# =====================================================
# SUBJECT GROUP (STREAM)
# =====================================================


class SubjectGroup(models.Model):

    name = models.CharField(max_length=100)
    code = models.CharField(max_length=20, unique=True)

    standard = models.ForeignKey(
        Standard,
        on_delete=models.CASCADE,
        related_name="subject_groups",
        limit_choices_to={"standard_type": "higher_secondary"},
    )

    is_active = models.BooleanField(default=True)

    class Meta:
        unique_together = ("standard", "name")

    def __str__(self):
        return self.name


# =====================================================
# SUBJECT
# =====================================================


class Subject(models.Model):

    SUBJECT_TYPES = [
        ("mandatory", "Mandatory"),
        ("elective", "Elective"),
        ("language", "Language"),
    ]

    name = models.CharField(max_length=100)
    code = models.CharField(max_length=20)

    standard = models.ForeignKey(
        Standard, on_delete=models.CASCADE, related_name="subjects"
    )

    category = models.ForeignKey(
        SubjectCategory, on_delete=models.CASCADE, related_name="subjects"
    )

    subject_group = models.ForeignKey(
        SubjectGroup,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="subjects",
    )

    subject_type = models.CharField(
        max_length=20, choices=SUBJECT_TYPES, default="mandatory"
    )

    book_document = models.FileField(
        upload_to=subject_book_upload_path,
        null=True,
        blank=True,
        help_text="Upload subject book/document",
    )
    is_active = models.BooleanField(default=True)

    class Meta:
        unique_together = ("standard", "code")

    def __str__(self):
        return self.name


# =====================================================
# ACADEMIC CLASS
# =====================================================


class AcademicClass(models.Model):

    academic_year = models.ForeignKey(
        AcademicYear, on_delete=models.CASCADE, related_name="classes"
    )

    standard = models.ForeignKey(
        Standard, on_delete=models.CASCADE, related_name="classes"
    )

    section = models.ForeignKey(
        Section, on_delete=models.CASCADE, related_name="classes"
    )

    subject_group = models.ForeignKey(
        SubjectGroup, null=True, blank=True, on_delete=models.SET_NULL
    )

    class_teacher = models.ForeignKey(
        "people.Teacher",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="class_teacher_classes",
    )

    assistant_teacher = models.ForeignKey(
        "people.Teacher",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="assistant_teacher_classes",
    )

    room_number = models.CharField(max_length=20, blank=True)

    timetable_document = models.FileField(
        upload_to="academic_classes/timetables/", null=True, blank=True
    )

    current_strength = models.PositiveIntegerField(default=0)

    max_strength = models.PositiveIntegerField(
        default=40, validators=[MinValueValidator(1), MaxValueValidator(100)]
    )

    boys_count = models.PositiveIntegerField(default=0)
    girls_count = models.PositiveIntegerField(default=0)

    annual_fee = models.DecimalField(
        max_digits=10, decimal_places=2, null=True, blank=True
    )

    passing_percentage = models.DecimalField(
        max_digits=5, decimal_places=2, null=True, blank=True
    )

    min_attendance_percentage = models.DecimalField(
        max_digits=5, decimal_places=2, default=75.00
    )

    is_active = models.BooleanField(default=True)
    is_frozen = models.BooleanField(default=False)

    notes = models.TextField(blank=True)

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        unique_together = ("academic_year", "standard", "section")

    def __str__(self):
        return f"{self.standard}-{self.section} ({self.academic_year})"


class ClassSubject(models.Model):

    academic_class = models.ForeignKey(
        AcademicClass, on_delete=models.CASCADE, related_name="class_subjects"
    )

    subject = models.ForeignKey(
        Subject, on_delete=models.CASCADE, related_name="class_subjects"
    )

    class Meta:
        unique_together = ("academic_class", "subject")

    def __str__(self):
        return f"{self.academic_class} - {self.subject}"


class StudentEnrollment(models.Model):

    student = models.ForeignKey(
        "people.Student", on_delete=models.CASCADE, related_name="enrollments"
    )

    academic_class = models.ForeignKey(
        AcademicClass, on_delete=models.CASCADE, related_name="enrollments"
    )

    roll_number = models.PositiveIntegerField()
    admission_date = models.DateField(null=True, blank=True)

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ("student", "academic_class")

    def __str__(self):
        return f"{self.student} - {self.academic_class}"


class StudentSubjectGroup(models.Model):

    enrollment = models.ForeignKey(
        StudentEnrollment, on_delete=models.CASCADE, related_name="subject_groups"
    )

    subject_group = models.ForeignKey(
        SubjectGroup, on_delete=models.CASCADE, related_name="student_enrollments"
    )

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ("enrollment", "subject_group")

    def __str__(self):
        return f"{self.enrollment} - {self.subject_group}"


class StudentSubject(models.Model):

    enrollment = models.ForeignKey(
        StudentEnrollment, on_delete=models.CASCADE, related_name="selected_subjects"
    )

    subject = models.ForeignKey(
        Subject, on_delete=models.CASCADE, related_name="students"
    )

    is_active = models.BooleanField(default=True)

    class Meta:
        unique_together = ("enrollment", "subject")

    def __str__(self):
        return f"{self.enrollment} - {self.subject}"


class SubjectTeacher(models.Model):

    academic_class = models.ForeignKey(
        AcademicClass, on_delete=models.CASCADE, related_name="subject_teachers"
    )

    subject = models.ForeignKey(
        Subject, on_delete=models.CASCADE, related_name="subject_teachers"
    )

    teacher = models.ForeignKey(
        "people.Teacher", on_delete=models.CASCADE, related_name="subject_teachers"
    )

    is_active = models.BooleanField(default=True)

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ("academic_class", "subject")

    def __str__(self):
        return f"{self.teacher} - {self.subject}"
