# students/models.py
"""
Student management models for student information and parent/guardian relationships.
"""
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.core.validators import RegexValidator
from academics.models import SchoolClass


class Student(models.Model):
    """
    Student information model for primary schools in Cameroon.
    
    This comprehensive model stores all information about students including
    personal details, contact information, medical information, academic
    history, and emergency contacts.
    
    Attributes:
        student_id (str): Unique student identifier
        first_name (str): Student's first name
        last_name (str): Student's last name
        date_of_birth (date): Student's birth date
        place_of_birth (str): Birth location
        gender (str): Gender from GENDER_CHOICES
        nationality (str): Student's nationality
        home_address (str): Residential address
        quarter (str): Neighborhood/district
        city (str): City of residence
        phone_number (str): Student's phone (if applicable)
        email (str): Student's email (if applicable)
        emergency_contact_name (str): Name of emergency contact
        emergency_contact_phone (str): Emergency contact number
        emergency_contact_relationship (str): Relationship to emergency contact
        blood_group (str): Blood type from choices
        allergies (str): Known allergies
        chronic_conditions (str): Chronic medical conditions
        medications (str): Current medications
        admission_date (date): Date of enrollment
        admission_class (str): Class at admission
        current_class (ForeignKey): Current class
        status (str): Current enrollment status
        photo (ImageField): Student photograph
        birth_certificate (FileField): Birth certificate document
        imported_from (str): Source of import
        original_data (JSONField): Original imported data
        created_at (datetime): When record was created
        updated_at (datetime): When record was last updated
        notes (str): Additional notes
    """
    
    # Gender choices
    GENDER_CHOICES = [
        ('M', _('Male')),
        ('F', _('Female')),
        ('U', _('Unknown/Unspecified')),
    ]
    
    # Student status
    STATUS_CHOICES = [
        ('active', _('Active')),
        ('inactive', _('Inactive')),
        ('graduated', _('Graduated')),
        ('transferred', _('Transferred')),
        ('suspended', _('Suspended')),
        ('withdrawn', _('Withdrawn')),
    ]
    
    CLASS_CHOICES = [
        ('pre_nursery', 'Pre-Nursery'),
        ('nursery1', 'Nursery 1'),
        ('nursery2', 'Nursery 2'),
        ('moyenne_section', 'Moyenne Section'),
        ('grande_section', 'Grande Section'),
        ('sil', 'SIL'),
        ('cp', 'CP'),
        ('ce1', 'CE1'),
        ('ce2', 'CE2'),
        ('cm1', 'CM1'),
        ('cm2', 'CM2'),
        ('class1', 'Class 1'),
        ('class2', 'Class 2'),
        ('class3', 'Class 3'),
        ('class4', 'Class 4'),
        ('class5', 'Class 5'),
        ('class6', 'Class 6'),
    ]
    
    # Cameroonian phone validator
    phone_regex = RegexValidator(
        regex=r'^\+?[1-9]\d{1,14}$',
        message="Phone number must be entered in the format: '+237XXXXXXXXX'."
    )
    
    # ========== IDENTIFICATION ==========
    student_id = models.CharField(
        max_length=20,
        unique=True,
        verbose_name=_("Student ID"),
        help_text=_("Unique identifier for the student (e.g., 2025-001)")
    )
    
    first_name = models.CharField(
        max_length=100,
        verbose_name=_("First Name")
    )
    
    last_name = models.CharField(
        max_length=100,
        verbose_name=_("Last Name")
    )
    
    date_of_birth = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Date of Birth")
    )
    
    place_of_birth = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        verbose_name=_("Place of Birth")
    )
    
    gender = models.CharField(
        max_length=1,
        choices=GENDER_CHOICES,
        default='U',
        blank=True,
        verbose_name=_("Gender")
    )
    
    nationality = models.CharField(
        max_length=50,
        default="Cameroonian",
        blank=True,
        verbose_name=_("Nationality")
    )
    
    # ========== CONTACT INFORMATION ==========
    home_address = models.TextField(
        blank=True,
        verbose_name=_("Home Address")
    )
    
    quarter = models.CharField(
        max_length=100,
        blank=True,
        verbose_name=_("Quarter/Neighborhood"),
        help_text=_("e.g., Bonapriso, Akwa, Bonanjo")
    )
    
    city = models.CharField(
        max_length=100,
        default="Douala",
        blank=True,
        verbose_name=_("City")
    )
    
    phone_number = models.CharField(
        validators=[phone_regex],
        max_length=17,
        blank=True,
        verbose_name=_("Phone Number")
    )
    
    email = models.EmailField(
        blank=True,
        verbose_name=_("Email Address")
    )
    
    # ========== EMERGENCY CONTACT ==========
    emergency_contact_name = models.CharField(
        max_length=100,
        blank=True,
        verbose_name=_("Emergency Contact Name")
    )
    
    emergency_contact_phone = models.CharField(
        validators=[phone_regex],
        max_length=17,
        blank=True,
        verbose_name=_("Emergency Contact Phone")
    )
    
    emergency_contact_relationship = models.CharField(
        max_length=50,
        blank=True,
        verbose_name=_("Relationship"),
        help_text=_("e.g., Father, Mother, Guardian")
    )
    
    # ========== MEDICAL INFORMATION ==========
    blood_group = models.CharField(
        max_length=7,
        blank=True,
        verbose_name=_("Blood Group"),
        choices=[
            ('A+', 'A+'), ('A-', 'A-'),
            ('B+', 'B+'), ('B-', 'B-'),
            ('AB+', 'AB+'), ('AB-', 'AB-'),
            ('O+', 'O+'), ('O-', 'O-'),
            ('unknown', 'Unknown'),
        ],
        default='unknown'
    )
    
    allergies = models.TextField(
        blank=True,
        verbose_name=_("Allergies"),
        help_text=_("List any allergies the student has")
    )
    
    chronic_conditions = models.TextField(
        blank=True,
        verbose_name=_("Chronic Conditions"),
        help_text=_("List any chronic medical conditions")
    )
    
    medications = models.TextField(
        blank=True,
        verbose_name=_("Current Medications"),
        help_text=_("List any medications the student is taking")
    )
    
    # ========== SCHOOL INFORMATION ==========
    admission_date = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Admission Date")
    )
    
    admission_class = models.CharField(
        max_length=20,
        choices=CLASS_CHOICES,
        blank=True,
        verbose_name=_("Admission Class")
    )
    
    current_class = models.ForeignKey(
        SchoolClass,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        verbose_name=_("Current Class"),
        related_name='students'
    )
    
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='active',
        verbose_name=_("Status")
    )
    
    # ========== PHOTO & DOCUMENTS ==========
    photo = models.ImageField(
        upload_to='student_photos/',
        blank=True,
        null=True,
        verbose_name=_("Student Photo")
    )
    
    birth_certificate = models.FileField(
        upload_to='documents/birth_certificates/',
        blank=True,
        null=True,
        verbose_name=_("Birth Certificate")
    )
    
    # ========== IMPORT TRACKING ==========
    imported_from = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        help_text="Source of import (e.g., 'Class 6 Excel')"
    )
    
    original_data = models.JSONField(
        blank=True,
        null=True,
        help_text="Original imported data as JSON"
    )
    
    # ========== METADATA ==========
    created_at = models.DateTimeField(
        auto_now_add=True,
        null=True,
        blank=True,
        verbose_name=_("Created At")
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        null=True,
        blank=True,
        verbose_name=_("Updated At")
    )
    
    notes = models.TextField(
        blank=True,
        verbose_name=_("Additional Notes")
    )
    
    class Meta:
        verbose_name = _("Student")
        verbose_name_plural = _("Students")
        ordering = ['student_id', 'last_name', 'first_name']
        indexes = [
            models.Index(fields=['student_id']),
            models.Index(fields=['last_name', 'first_name']),
            models.Index(fields=['current_class']),
            models.Index(fields=['status']),
        ]
    
    def __str__(self):
        """Return string representation of the student."""
        return f"{self.student_id} - {self.first_name} {self.last_name}"
    
    def get_full_name(self):
        """
        Return the full name of the student.
        
        Returns:
            str: Combined first and last name.
        """
        return f"{self.first_name} {self.last_name}".strip()
    
    def get_age(self):
        """
        Calculate student's current age based on date of birth.
        
        Returns:
            int or None: Age in years, or None if DOB not set.
        """
        if not self.date_of_birth:
            return None
        from datetime import date
        today = date.today()
        age = today.year - self.date_of_birth.year
        if (today.month, today.day) < (self.date_of_birth.month, self.date_of_birth.day):
            age -= 1
        return age
    
    def is_active(self):
        """
        Check if student is currently active.
        
        Returns:
            bool: True if status is 'active'.
        """
        return self.status == 'active'
    
    def get_emergency_contact_info(self):
        """
        Get formatted emergency contact information.
        
        Returns:
            str: Formatted string with emergency contact details.
        """
        if self.emergency_contact_name and self.emergency_contact_phone:
            rel = f" ({self.emergency_contact_relationship})" if self.emergency_contact_relationship else ""
            return f"{self.emergency_contact_name}{rel}: {self.emergency_contact_phone}"
        return "No emergency contact on file"


class ParentGuardian(models.Model):
    """
    Parent or Guardian information linked to students.
    
    This model stores detailed information about parents and guardians,
    including contact preferences, mobile money details, and authorization
    to pick up students.
    
    Attributes:
        student (ForeignKey): Student this parent is linked to
        first_name (str): Parent's first name
        last_name (str): Parent's last name
        relationship (str): Relationship to student from RELATIONSHIP_CHOICES
        phone (str): Primary phone number
        alternate_phone (str): Secondary phone number
        email (str): Email address
        address (str): Residential address
        occupation (str): Occupation from OCCUPATION_CHOICES
        employer (str): Employer name
        education_level (str): Education level from EDUCATION_CHOICES
        mobile_money_number (str): Mobile money account number
        mobile_money_provider (str): Mobile money provider
        preferred_language (str): Preferred language for communication
        receive_sms (bool): Whether to receive SMS notifications
        receive_email (bool): Whether to receive email notifications
        receive_whatsapp (bool): Whether to receive WhatsApp messages
        is_primary_contact (bool): Whether this is the primary contact
        can_pick_up (bool): Whether authorized to pick up student
        created_at (datetime): When record was created
        updated_at (datetime): When record was last updated
        notes (str): Additional notes
    """
    
    RELATIONSHIP_CHOICES = [
        ('father', _('Father')),
        ('mother', _('Mother')),
        ('guardian', _('Guardian')),
        ('grandparent', _('Grandparent')),
        ('sibling', _('Sibling')),
        ('aunt', _('Aunt')),
        ('uncle', _('Uncle')),
        ('other', _('Other')),
    ]
    
    OCCUPATION_CHOICES = [
        ('teacher', _('Teacher')),
        ('nurse', _('Nurse')),
        ('engineer', _('Engineer')),
        ('doctor', _('Doctor')),
        ('lawyer', _('Lawyer')),
        ('business', _('Business Owner')),
        ('civil_servant', _('Civil Servant')),
        ('farmer', _('Farmer')),
        ('driver', _('Driver')),
        ('trader', _('Trader')),
        ('housewife', _('Housewife')),
        ('other', _('Other')),
    ]
    
    EDUCATION_CHOICES = [
        ('none', _('No Formal Education')),
        ('primary', _('Primary School')),
        ('secondary', _('Secondary School')),
        ('high_school', _('High School')),
        ('university', _('University')),
        ('postgraduate', _('Postgraduate')),
    ]
    
    phone_regex = RegexValidator(
        regex=r'^\+?[1-9]\d{1,14}$',
        message="Phone number must be entered in the format: '+237XXXXXXXXX'."
    )
    
    # ========== BASIC INFORMATION ==========
    student = models.ForeignKey(
        Student,
        on_delete=models.CASCADE,
        related_name='parents',
        verbose_name=_("Student")
    )
    
    first_name = models.CharField(
        max_length=100,
        verbose_name=_("First Name")
    )
    
    last_name = models.CharField(
        max_length=100,
        verbose_name=_("Last Name")
    )
    
    relationship = models.CharField(
        max_length=20,
        choices=RELATIONSHIP_CHOICES,
        verbose_name=_("Relationship to Student")
    )
    
    # ========== CONTACT INFORMATION ==========
    phone = models.CharField(
        validators=[phone_regex],
        max_length=17,
        verbose_name=_("Phone Number")
    )
    
    alternate_phone = models.CharField(
        validators=[phone_regex],
        max_length=17,
        blank=True,
        verbose_name=_("Alternate Phone Number")
    )
    
    email = models.EmailField(
        blank=True,
        verbose_name=_("Email Address")
    )
    
    address = models.TextField(
        blank=True,
        verbose_name=_("Address")
    )
    
    # ========== PERSONAL INFORMATION ==========
    occupation = models.CharField(
        max_length=50,
        choices=OCCUPATION_CHOICES,
        blank=True,
        verbose_name=_("Occupation")
    )
    
    employer = models.CharField(
        max_length=100,
        blank=True,
        verbose_name=_("Employer")
    )
    
    education_level = models.CharField(
        max_length=20,
        choices=EDUCATION_CHOICES,
        blank=True,
        verbose_name=_("Education Level")
    )
    
    # ========== MOBILE MONEY INFORMATION ==========
    mobile_money_number = models.CharField(
        max_length=20,
        blank=True,
        verbose_name=_("Mobile Money Number")
    )
    
    mobile_money_provider = models.CharField(
        max_length=10,
        choices=[
            ('mtn', 'MTN Mobile Money'),
            ('orange', 'Orange Money'),
            ('none', 'None'),
        ],
        default='none',
        verbose_name=_("Mobile Money Provider")
    )
    
    # ========== COMMUNICATION PREFERENCES ==========
    preferred_language = models.CharField(
        max_length=10,
        choices=[
            ('fr', 'French'),
            ('en', 'English'),
            ('both', 'Both'),
        ],
        default='fr',
        verbose_name=_("Preferred Language")
    )
    
    receive_sms = models.BooleanField(
        default=True,
        verbose_name=_("Receive SMS Notifications")
    )
    
    receive_email = models.BooleanField(
        default=False,
        verbose_name=_("Receive Email Notifications")
    )
    
    receive_whatsapp = models.BooleanField(
        default=True,
        verbose_name=_("Receive WhatsApp Messages")
    )
    
    # ========== ADMINISTRATIVE ==========
    is_primary_contact = models.BooleanField(
        default=False,
        verbose_name=_("Primary Contact"),
        help_text=_("Is this the primary contact for the student?")
    )
    
    can_pick_up = models.BooleanField(
        default=True,
        verbose_name=_("Can Pick Up Student"),
        help_text=_("Is this person authorized to pick up the student from school?")
    )
    
    # ========== METADATA ==========
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_("Created At")
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name=_("Updated At")
    )
    
    notes = models.TextField(
        blank=True,
        verbose_name=_("Additional Notes")
    )
    
    class Meta:
        verbose_name = _("Parent/Guardian")
        verbose_name_plural = _("Parents/Guardians")
        ordering = ['student', '-is_primary_contact', 'last_name', 'first_name']
        unique_together = ['student', 'phone']
    
    def __str__(self):
        """Return string representation of the parent/guardian."""
        primary = " (Primary)" if self.is_primary_contact else ""
        return f"{self.first_name} {self.last_name} - {self.get_relationship_display()}{primary}"
    
    def get_full_name(self):
        """
        Return the full name of the parent/guardian.
        
        Returns:
            str: Combined first and last name.
        """
        return f"{self.first_name} {self.last_name}".strip()
    
    def get_contact_info(self):
        """
        Get formatted contact information.
        
        Returns:
            str: Formatted string with all contact details.
        """
        info = []
        if self.phone:
            info.append(f"Phone: {self.phone}")
        if self.alternate_phone:
            info.append(f"Alt: {self.alternate_phone}")
        if self.email:
            info.append(f"Email: {self.email}")
        if self.mobile_money_number and self.mobile_money_provider != 'none':
            info.append(f"MoMo: {self.mobile_money_number} ({self.get_mobile_money_provider_display()})")
        return " | ".join(info)