from django.db import models
from django.core.validators import EmailValidator


class Teacher(models.Model):
    # External reference to master database user
    external_user_id = models.CharField(
        max_length=100,
        unique=True,
        null=True,
        blank=True,
        help_text="User ID from master database",
    )

    # Personal Information
    first_name = models.CharField(max_length=100, null=True, blank=True)
    middle_name = models.CharField(max_length=100, null=True, blank=True)
    last_name = models.CharField(max_length=100, null=True, blank=True)

    # Contact Information
    email = models.EmailField(
        max_length=255,
        null=True,
        blank=True,
        validators=[EmailValidator()],
        help_text="Primary email address",
    )
    phone = models.CharField(
        max_length=20, null=True, blank=True, help_text="Primary phone number"
    )
    alternate_phone = models.CharField(
        max_length=20, null=True, blank=True, help_text="Alternate phone number"
    )

    # Professional Information
    employee_id = models.CharField(max_length=50, null=True, blank=True, unique=True)
    qualification = models.CharField(max_length=255, null=True, blank=True)
    specialization = models.CharField(max_length=255, null=True, blank=True)

    # Employment Details
    date_of_joining = models.DateField(null=True, blank=True)
    employment_type = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        choices=[
            ("FULL_TIME", "Full Time"),
            ("PART_TIME", "Part Time"),
            ("CONTRACT", "Contract"),
            ("VISITING", "Visiting"),
        ],
    )

    # Address Information
    address_line_1 = models.TextField(null=True, blank=True)
    address_line_2 = models.TextField(null=True, blank=True)
    city = models.CharField(max_length=100, null=True, blank=True)
    state = models.CharField(max_length=100, null=True, blank=True)
    country = models.CharField(max_length=100, null=True, blank=True)
    pincode = models.CharField(max_length=20, null=True, blank=True)

    # Personal Details
    date_of_birth = models.DateField(null=True, blank=True)
    gender = models.CharField(
        max_length=20,
        null=True,
        blank=True,
        choices=[
            ("MALE", "Male"),
            ("FEMALE", "Female"),
            ("OTHER", "Other"),
            ("PREFER_NOT_TO_SAY", "Prefer not to say"),
        ],
    )

    # Emergency Contact
    emergency_contact_name = models.CharField(max_length=255, null=True, blank=True)
    emergency_contact_phone = models.CharField(max_length=20, null=True, blank=True)
    emergency_contact_relation = models.CharField(max_length=100, null=True, blank=True)

    # Status and Metadata
    is_active = models.BooleanField(default=True)
    profile_image = models.ImageField(
        upload_to="teachers/profile_images/", null=True, blank=True
    )

    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        db_table = "teachers"
        verbose_name = "Teacher"
        verbose_name_plural = "Teachers"
        ordering = ["last_name", "first_name"]
        indexes = [
            models.Index(fields=["external_user_id"]),
            models.Index(fields=["email"]),
            models.Index(fields=["employee_id"]),
            models.Index(fields=["is_active"]),
        ]

    def __str__(self):
        return f"{self.first_name} {self.last_name} ({self.employee_id or 'No ID'})"

    @property
    def full_name(self):
        """Return full name of the teacher"""
        parts = [self.first_name, self.middle_name, self.last_name]
        return " ".join(filter(None, parts))


class Parent(models.Model):
    # External reference to master database user
    external_user_id = models.CharField(
        max_length=100,
        unique=True,
        null=True,
        blank=True,
        help_text="User ID from master database",
    )

    # Personal Information
    first_name = models.CharField(max_length=100, null=True, blank=True)
    middle_name = models.CharField(max_length=100, null=True, blank=True)
    last_name = models.CharField(max_length=100, null=True, blank=True)

    # Contact Information
    email = models.EmailField(
        max_length=255,
        null=True,
        blank=True,
        validators=[EmailValidator()],
        help_text="Primary email address",
    )
    phone = models.CharField(
        max_length=20, null=True, blank=True, help_text="Primary phone number"
    )
    alternate_phone = models.CharField(
        max_length=20, null=True, blank=True, help_text="Alternate phone number"
    )

    # Parent Details
    parent_type = models.CharField(
        max_length=20,
        null=True,
        blank=True,
        choices=[
            ("FATHER", "Father"),
            ("MOTHER", "Mother"),
            ("GUARDIAN", "Guardian"),
            ("OTHER", "Other"),
        ],
    )
    occupation = models.CharField(max_length=255, null=True, blank=True)
    annual_income = models.DecimalField(
        max_digits=15,
        decimal_places=2,
        null=True,
        blank=True,
        help_text="Annual income in local currency",
    )

    # Address Information
    address_line_1 = models.TextField(null=True, blank=True)
    address_line_2 = models.TextField(null=True, blank=True)
    city = models.CharField(max_length=100, null=True, blank=True)
    state = models.CharField(max_length=100, null=True, blank=True)
    country = models.CharField(max_length=100, null=True, blank=True)
    pincode = models.CharField(max_length=20, null=True, blank=True)

    # Personal Details
    date_of_birth = models.DateField(null=True, blank=True)
    gender = models.CharField(
        max_length=20,
        null=True,
        blank=True,
        choices=[
            ("MALE", "Male"),
            ("FEMALE", "Female"),
            ("OTHER", "Other"),
            ("PREFER_NOT_TO_SAY", "Prefer not to say"),
        ],
    )

    # Additional Information
    identification_number = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        help_text="Aadhar, SSN, or other government ID",
    )
    identification_type = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        choices=[
            ("AADHAR", "Aadhar"),
            ("SSN", "Social Security Number"),
            ("PAN", "PAN"),
            ("PASSPORT", "Passport"),
            ("DRIVING_LICENSE", "Driving License"),
            ("OTHER", "Other"),
        ],
    )

    # Status and Metadata
    is_primary = models.BooleanField(
        default=False, help_text="Is this the primary parent?"
    )
    is_active = models.BooleanField(default=True)
    profile_image = models.ImageField(
        upload_to="parents/profile_images/", null=True, blank=True
    )

    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        db_table = "parents"
        verbose_name = "Parent"
        verbose_name_plural = "Parents"
        ordering = ["last_name", "first_name"]
        indexes = [
            models.Index(fields=["external_user_id"]),
            models.Index(fields=["email"]),
            models.Index(fields=["phone"]),
            models.Index(fields=["is_primary"]),
            models.Index(fields=["is_active"]),
        ]

    def __str__(self):
        return f"{self.first_name} {self.last_name} ({self.parent_type or 'Parent'})"

    @property
    def full_name(self):
        """Return full name of the parent"""
        parts = [self.first_name, self.middle_name, self.last_name]
        return " ".join(filter(None, parts))


class Student(models.Model):
    # External reference to master database user
    external_user_id = models.CharField(
        max_length=100,
        unique=True,
        null=True,
        blank=True,
        help_text="User ID from master database",
    )

    # Personal Information
    first_name = models.CharField(max_length=100, null=True, blank=True)
    middle_name = models.CharField(max_length=100, null=True, blank=True)
    last_name = models.CharField(max_length=100, null=True, blank=True)

    # Student Identification
    student_id = models.CharField(
        max_length=50,
        unique=True,
        null=True,
        blank=True,
        help_text="Unique student ID within the system",
    )
    roll_number = models.CharField(max_length=50, null=True, blank=True)

    # Personal Details
    date_of_birth = models.DateField(null=True, blank=True)
    gender = models.CharField(
        max_length=20,
        null=True,
        blank=True,
        choices=[
            ("MALE", "Male"),
            ("FEMALE", "Female"),
            ("OTHER", "Other"),
            ("PREFER_NOT_TO_SAY", "Prefer not to say"),
        ],
    )

    # Contact Information
    personal_email = models.EmailField(
        max_length=255,
        null=True,
        blank=True,
        validators=[EmailValidator()],
        help_text="Student's personal email",
    )
    personal_phone = models.CharField(
        max_length=20,
        null=True,
        blank=True,
        help_text="Student's personal phone number",
    )

    # Address Information
    permanent_address_line_1 = models.TextField(null=True, blank=True)
    permanent_address_line_2 = models.TextField(null=True, blank=True)
    permanent_city = models.CharField(max_length=100, null=True, blank=True)
    permanent_state = models.CharField(max_length=100, null=True, blank=True)
    permanent_country = models.CharField(max_length=100, null=True, blank=True)
    permanent_pincode = models.CharField(max_length=20, null=True, blank=True)

    correspondence_address_line_1 = models.TextField(null=True, blank=True)
    correspondence_address_line_2 = models.TextField(null=True, blank=True)
    correspondence_city = models.CharField(max_length=100, null=True, blank=True)
    correspondence_state = models.CharField(max_length=100, null=True, blank=True)
    correspondence_country = models.CharField(max_length=100, null=True, blank=True)
    correspondence_pincode = models.CharField(max_length=20, null=True, blank=True)

    # Academic Information
    admission_date = models.DateField(null=True, blank=True)
    admission_number = models.CharField(max_length=50, null=True, blank=True)

    # Identification Documents
    identification_number = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        help_text="Aadhar, SSN, or other government ID",
    )
    identification_type = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        choices=[
            ("AADHAR", "Aadhar"),
            ("SSN", "Social Security Number"),
            ("PAN", "PAN"),
            ("PASSPORT", "Passport"),
            ("DRIVING_LICENSE", "Driving License"),
            ("OTHER", "Other"),
        ],
    )

    # Health Information
    blood_group = models.CharField(
        max_length=10,
        null=True,
        blank=True,
        choices=[
            ("A+", "A+"),
            ("A-", "A-"),
            ("B+", "B+"),
            ("B-", "B-"),
            ("O+", "O+"),
            ("O-", "O-"),
            ("AB+", "AB+"),
            ("AB-", "AB-"),
        ],
    )
    known_allergies = models.TextField(null=True, blank=True)
    medical_conditions = models.TextField(null=True, blank=True)

    # Emergency Contact
    emergency_contact_name = models.CharField(max_length=255, null=True, blank=True)
    emergency_contact_phone = models.CharField(max_length=20, null=True, blank=True)
    emergency_contact_relation = models.CharField(max_length=100, null=True, blank=True)

    # Status and Metadata
    is_active = models.BooleanField(default=True)
    profile_image = models.ImageField(
        upload_to="students/profile_images/", null=True, blank=True
    )

    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        db_table = "students"
        verbose_name = "Student"
        verbose_name_plural = "Students"
        ordering = ["last_name", "first_name"]
        indexes = [
            models.Index(fields=["external_user_id"]),
            models.Index(fields=["student_id"]),
            models.Index(fields=["roll_number"]),
            models.Index(fields=["admission_number"]),
            models.Index(fields=["is_active"]),
        ]

    def __str__(self):
        return f"{self.first_name} {self.last_name} ({self.student_id or 'No ID'})"

    @property
    def full_name(self):
        """Return full name of the student"""
        parts = [self.first_name, self.middle_name, self.last_name]
        return " ".join(filter(None, parts))

    @property
    def age(self):
        """Calculate student's age"""
        if not self.date_of_birth:
            return None
        from datetime import date

        today = date.today()
        return (
            today.year
            - self.date_of_birth.year
            - (
                (today.month, today.day)
                < (self.date_of_birth.month, self.date_of_birth.day)
            )
        )


class StudentParent(models.Model):
    """Many-to-many relationship between Students and Parents"""

    student = models.ForeignKey(
        Student, on_delete=models.CASCADE, related_name="student_parents"
    )
    parent = models.ForeignKey(
        Parent, on_delete=models.CASCADE, related_name="student_parents"
    )

    # Relationship Details
    relationship = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        choices=[
            ("FATHER", "Father"),
            ("MOTHER", "Mother"),
            ("GUARDIAN", "Guardian"),
            ("GRANDFATHER", "Grandfather"),
            ("GRANDMOTHER", "Grandmother"),
            ("UNCLE", "Uncle"),
            ("AUNT", "Aunt"),
            ("SIBLING", "Sibling"),
            ("OTHER", "Other"),
        ],
    )

    # Responsibility and Permissions
    is_primary_contact = models.BooleanField(
        default=False, help_text="Is this the primary contact for the student?"
    )
    can_pickup = models.BooleanField(
        default=False, help_text="Can this parent pick up the student from school?"
    )
    has_medical_consent = models.BooleanField(
        default=False, help_text="Can this parent give medical consent?"
    )
    has_academic_access = models.BooleanField(
        default=True, help_text="Can this parent access academic information?"
    )

    # Communication Preferences
    receive_notifications = models.BooleanField(default=True)
    notification_preferences = models.JSONField(
        null=True,
        blank=True,
        default=dict,
        help_text="JSON field for notification preferences",
    )

    # Status
    is_active = models.BooleanField(default=True)

    # Timestamps
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)

    class Meta:
        db_table = "student_parents"
        verbose_name = "Student Parent Relationship"
        verbose_name_plural = "Student Parent Relationships"
        unique_together = ["student", "parent"]
        ordering = ["student__last_name", "student__first_name"]
        indexes = [
            models.Index(fields=["student", "parent"]),
            models.Index(fields=["is_active"]),
            models.Index(fields=["is_primary_contact"]),
            models.Index(fields=["relationship"]),
        ]

    def __str__(self):
        return f"{self.parent.full_name} - {self.student.full_name} ({self.relationship or 'Parent'})"
