"""
Модели данных для системы проверки домашних заданий.
Содержит модели для:
- Профилей пользователей (студенты и преподаватели)
- Домашних заданий
- Отправленных работ студентов
"""
import os
from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
User = get_user_model()
[документация]
def validate_file_size(file):
    """
    Валидатор размера файла (максимум 10 МБ).
    Args:
        file: Загружаемый файл
    Raises:
        ValidationError: Если размер файла превышает лимит
    """
    max_size_mb = 10
    if file.size > max_size_mb * 1024 * 1024:
        raise ValidationError(f"Максимальный размер файла {max_size_mb}МБ. Ваш файл: {file.size / (1024 * 1024):.2f}МБ") 
[документация]
def validate_file_extension(file):
    """
    Валидатор расширения файла.
    Args:
        file: Загружаемый файл
    Raises:
        ValidationError: Если расширение файла не разрешено
    """
    ext = os.path.splitext(file.name)[1].lower()
    valid_extensions = [".pdf", ".doc", ".docx", ".txt", ".py", ".zip", ".jpg", ".jpeg", ".png"]
    if ext not in valid_extensions:
        raise ValidationError(f"Неподдерживаемый формат файла. Разрешены: {', '.join(valid_extensions)}") 
[документация]
class UserProfile(models.Model):
    """Профиль пользователя с ролью"""
    ROLE_CHOICES = [
        ("student", "Студент"),
        ("teacher", "Преподаватель"),
    ]
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
    role = models.CharField(max_length=10, choices=ROLE_CHOICES, default="student", verbose_name="Роль")
    class Meta:
        verbose_name = "Профиль пользователя"
        verbose_name_plural = "Профили пользователей"
    def __str__(self):
        return f"{self.user.username} - {self.get_role_display()}"
    @property
    def is_student(self):
        return self.role == "student"
    @property
    def is_teacher(self):
        return self.role == "teacher" 
[документация]
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    """Автоматически создаем профиль при создании пользователя"""
    if created:
        UserProfile.objects.create(user=instance) 
[документация]
@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    """Сохраняем профиль при сохранении пользователя"""
    if hasattr(instance, "profile"):
        instance.profile.save() 
[документация]
class Course(models.Model):
    """Модель курса"""
    title = models.CharField(max_length=200, verbose_name="Название курса")
    description = models.TextField(verbose_name="Описание курса")
    teachers = models.ManyToManyField(
        User,
        related_name="teaching_courses",
        verbose_name="Преподаватели",
        limit_choices_to={"profile__role": "teacher"},
    )
    students = models.ManyToManyField(
        User,
        related_name="enrolled_courses",
        blank=True,
        verbose_name="Студенты",
        limit_choices_to={"profile__role": "student"},
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
    class Meta:
        verbose_name = "Курс"
        verbose_name_plural = "Курсы"
        ordering = ["title"]
    def __str__(self):
        return self.title 
[документация]
class Homework(models.Model):
    """Модель домашнего задания"""
    course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name="homeworks", verbose_name="Курс")
    title = models.CharField(max_length=200, verbose_name="Заголовок")
    description = models.TextField(verbose_name="Описание")
    due_date = models.DateTimeField(verbose_name="Срок сдачи")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания")
    class Meta:
        verbose_name = "Домашнее задание"
        verbose_name_plural = "Домашние задания"
        ordering = ["-created_at"]
    def __str__(self):
        return f"{self.course.title} - {self.title}" 
[документация]
class Submission(models.Model):
    """Модель отправки работы студентом"""
    homework = models.ForeignKey(
        Homework, on_delete=models.CASCADE, related_name="submissions", verbose_name="Домашнее задание"
    )
    student = models.ForeignKey(User, on_delete=models.CASCADE, related_name="submissions", verbose_name="Студент")
    solution_file = models.FileField(
        upload_to="submissions/",
        verbose_name="Файл с решением",
        validators=[validate_file_size, validate_file_extension],
    )
    submitted_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата отправки")
    grade = models.IntegerField(null=True, blank=True, verbose_name="Оценка")
    feedback = models.TextField(blank=True, verbose_name="Отзыв преподавателя")
    class Meta:
        verbose_name = "Отправка работы"
        verbose_name_plural = "Отправки работ"
        ordering = ["-submitted_at"]
        unique_together = ["homework", "student"]
    def __str__(self):
        return f"{self.student.username} - {self.homework.title}" 
[документация]
class CourseEnrollmentRequest(models.Model):
    """Модель заявки студента на зачисление на курс"""
    STATUS_CHOICES = [
        ("pending", "На рассмотрении"),
        ("approved", "Одобрена"),
        ("rejected", "Отклонена"),
    ]
    course = models.ForeignKey(
        Course,
        on_delete=models.CASCADE,
        related_name="enrollment_requests",
        verbose_name="Курс",
    )
    student = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="course_requests",
        verbose_name="Студент",
        limit_choices_to={"profile__role": "student"},
    )
    status = models.CharField(
        max_length=10,
        choices=STATUS_CHOICES,
        default="pending",
        verbose_name="Статус",
    )
    message = models.TextField(
        blank=True,
        verbose_name="Сообщение от студента",
        help_text="Опциональное сообщение преподавателю",
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата подачи")
    processed_at = models.DateTimeField(null=True, blank=True, verbose_name="Дата обработки")
    processed_by = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="processed_requests",
        verbose_name="Обработал",
    )
    class Meta:
        verbose_name = "Заявка на курс"
        verbose_name_plural = "Заявки на курсы"
        ordering = ["-created_at"]
        unique_together = ["course", "student"]
    def __str__(self):
        return f"{self.student.username} → {self.course.title} ({self.get_status_display()})"