# core/models.py
"""
Core models for the school management system including custom user and school.
"""
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _


class CustomUser(AbstractUser):
    """
    Custom user model for the school management system.
    
    Extends Django's AbstractUser to add school-specific fields and role-based
    access control. This model handles all user types including administrators,
    teachers, parents, and support staff.
    
    Attributes:
        user_type (str): Type of user from USER_TYPE_CHOICES
        phone (str): Primary phone number
        mobile_money_number (str): Mobile money account for payments
        profile_picture (ImageField): User's profile photo
        employee_id (str): Unique identifier for staff members
        teacher_id (str): Specific identifier for teachers
        access_level (int): Numeric level for permission hierarchy
        oversees_section (str): Section managed by head teachers
        financial_access (bool): Whether user can access financial data
        is_primary_contact (bool): For parents, whether this is primary contact
    """
    
    USER_TYPE_CHOICES = [
        ('super_admin', 'Super Administrator'),
        ('proprietor', 'Proprietor'),
        ('school_admin', 'School Administrator'),
        ('head_master', 'Head Master'),
        ('head_mistress', 'Head Mistress'),
        ('bursar', 'Bursar/Accountant'),
        ('teacher', 'Teacher'),
        ('class_teacher', 'Class Teacher'),
        ('subject_teacher', 'Subject Teacher'),
        ('parent', 'Parent/Guardian'),
        ('secretary', 'Secretary'),
        ('driver', 'Driver'),
        ('cleaner', 'Cleaner'),
        ('canteen', 'Canteen Staff'),
        ('security', 'Security'),
        ('support', 'Support Staff'),
    ]
    
    SECTION_CHOICES = [
        ('english', 'English Section'),
        ('french', 'French Section'),
        ('bilingual', 'Bilingual Section'),
        ('nursery', 'Nursery Section'),
        ('none', 'None'),
    ]
    
    user_type = models.CharField(
        max_length=20, 
        choices=USER_TYPE_CHOICES, 
        default='Welcome'
    )
    phone = models.CharField(
        max_length=20, 
        blank=True
    )
    mobile_money_number = models.CharField(
        max_length=20, 
        blank=True
    )
    profile_picture = models.ImageField(
        upload_to='profiles/', 
        blank=True, 
        null=True
    )
    
    # Staff/Teacher fields
    employee_id = models.CharField(
        max_length=20, 
        blank=True, 
        unique=True, 
        null=True
    )
    teacher_id = models.CharField(
        max_length=20, 
        blank=True
    )
    
    # Role-based access control
    access_level = models.IntegerField(
        default=1, 
        help_text="Higher number = more access"
    )
    oversees_section = models.CharField(
        max_length=20, 
        choices=SECTION_CHOICES, 
        default='none'
    )
    financial_access = models.BooleanField(
        default=False
    )
    
    # Parent-specific fields
    is_primary_contact = models.BooleanField(
        default=False
    )
    
    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")
        indexes = [
            models.Index(fields=['user_type']),
            models.Index(fields=['employee_id']),
        ]
    
    def __str__(self):
        """Return string representation of the user."""
        return f"{self.get_full_name() or self.username} ({self.get_user_type_display()})"
    
    def get_full_name(self):
        """
        Return the full name of the user.
        
        Returns:
            str: Combined first and last name, or username if not available.
        """
        full_name = super().get_full_name()
        return full_name if full_name else self.username
    
    def has_financial_access(self):
        """
        Check if user has permission to access financial data.
        
        Returns:
            bool: True if user has financial access by role or permission.
        """
        return self.financial_access or self.user_type in ['super_admin', 'proprietor', 'bursar']
    
    def is_head_teacher(self):
        """
        Check if user is a head teacher (master or mistress).
        
        Returns:
            bool: True if user is head_master or head_mistress.
        """
        return self.user_type in ['head_master', 'head_mistress']
    
    def get_accessible_sections(self):
        """
        Get list of sections this user has access to.
        
        Returns:
            list: Section codes that the user can access.
        """
        if self.user_type in ['super_admin', 'proprietor']:
            return dict(self.SECTION_CHOICES).keys()
        if self.is_head_teacher():
            return [self.oversees_section]
        return []


class School(models.Model):
    """
    Represents the school institution itself.
    
    This model stores information about the school, including contact details,
    academic settings, and configuration options. Multiple schools can be
    managed in a single installation (for school groups/chains).
    
    Attributes:
        name (str): Official school name
        code (str): Unique school code
        address (str): Physical address
        city (str): City location
        quarter (str): Neighborhood/district
        phone (str): Main contact number
        email (str): General email address
        website (URLField): School website URL
        principal_name (str): Name of principal/head teacher
        principal_phone (str): Principal's contact number
        academic_year (str): Current academic year
        current_term (int): Current term (1, 2, or 3)
        is_bilingual (bool): Whether school offers bilingual education
        default_language (str): Primary language of instruction
        offline_mode (bool): Whether offline sync is enabled
        mobile_money_enabled (bool): Whether mobile payments are accepted
        sms_alerts (bool): Whether SMS notifications are active
    """
    
    name = models.CharField(
        max_length=200
    )
    code = models.CharField(
        max_length=20, 
        unique=True
    )
    address = models.TextField()
    city = models.CharField(
        max_length=100, 
        default="Douala"
    )
    quarter = models.CharField(
        max_length=100, 
        blank=True
    )
    phone = models.CharField(
        max_length=20
    )
    email = models.EmailField(
        blank=True
    )
    website = models.URLField(
        blank=True
    )
    principal_name = models.CharField(
        max_length=100
    )
    principal_phone = models.CharField(
        max_length=20, 
        blank=True
    )
    
    # Academic Settings
    academic_year = models.CharField(
        max_length=9, 
        default="2025-2026"
    )
    current_term = models.PositiveSmallIntegerField(
        default=1, 
        choices=[(1, 'Term 1'), (2, 'Term 2'), (3, 'Term 3')]
    )
    is_bilingual = models.BooleanField(
        default=True
    )
    default_language = models.CharField(
        max_length=10, 
        choices=[('fr', 'French'), ('en', 'English'), ('both', 'Bilingual')],
        default='both'
    )
    
    # Technical Settings
    offline_mode = models.BooleanField(
        default=True
    )
    mobile_money_enabled = models.BooleanField(
        default=True
    )
    sms_alerts = models.BooleanField(
        default=True
    )
    
    class Meta:
        verbose_name = _("School")
        verbose_name_plural = _("Schools")
    
    def __str__(self):
        """Return string representation of the school."""
        return f"{self.name} - {self.quarter or self.city}"
    
    def get_full_address(self):
        """
        Get the complete formatted address.
        
        Returns:
            str: Complete address including quarter and city.
        """
        parts = [self.address]
        if self.quarter:
            parts.append(self.quarter)
        parts.append(self.city)
        return ", ".join(parts)