"""
Модели для домашних заданий.
"""
from django.db import models
from django.utils import timezone
from django.core.validators import MinValueValidator, MaxValueValidator
import uuid
import os


def homework_file_upload_path(instance, filename):
    """Путь для загрузки файлов заданий."""
    ext = filename.split('.')[-1]
    filename = f"{uuid.uuid4()}.{ext}"
    return os.path.join('homework', 'assignments', str(instance.id), filename)


def submission_file_upload_path(instance, filename):
    """Путь для загрузки файлов решений."""
    ext = filename.split('.')[-1]
    filename = f"{uuid.uuid4()}.{ext}"
    return os.path.join('homework', 'submissions', str(instance.id), filename)


class Homework(models.Model):
    """
    Модель домашнего задания.
    """
    
    STATUS_CHOICES = [
        ('draft', 'Черновик'),
        ('published', 'Опубликовано'),
        ('archived', 'В архиве'),
    ]
    
    # Основная информация
    title = models.CharField(
        max_length=255,
        verbose_name='Название'
    )
    
    description = models.TextField(
        blank=True,
        default='',
        verbose_name='Описание задания'
    )
    
    # Автор и связи
    mentor = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='created_homeworks',
        limit_choices_to={'role': 'mentor'},
        verbose_name='Ментор'
    )
    
    lesson = models.ForeignKey(
        'schedule.Lesson',
        on_delete=models.SET_NULL,
        related_name='homeworks',
        null=True,
        blank=True,
        verbose_name='Занятие'
    )
    
    # Кому назначено
    assigned_to = models.ManyToManyField(
        'users.User',
        related_name='assigned_homeworks',
        blank=True,
        verbose_name='Назначено'
    )
    
    # Файлы задания
    attachment = models.FileField(
        upload_to=homework_file_upload_path,
        blank=True,
        max_length=500,
        verbose_name='Файл задания'
    )
    
    attachment_url = models.URLField(
        blank=True,
        max_length=500,
        verbose_name='Ссылка на материал'
    )
    
    # Дедлайн
    deadline = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дедлайн',
        db_index=True
    )
    
    # Баллы (по умолчанию шкала 1–5, проходной не учитывается)
    max_score = models.IntegerField(
        default=5,
        validators=[MinValueValidator(1), MaxValueValidator(100)],
        verbose_name='Максимальный балл'
    )
    
    passing_score = models.IntegerField(
        default=1,
        validators=[MinValueValidator(0)],
        verbose_name='Проходной балл'
    )
    
    # Настройки
    allow_late_submission = models.BooleanField(
        default=False,
        verbose_name='Разрешить сдачу после дедлайна'
    )
    
    auto_check_enabled = models.BooleanField(
        default=False,
        verbose_name='Автоматическая проверка'
    )
    
    ai_check_enabled = models.BooleanField(
        default=False,
        verbose_name='AI проверка'
    )
    
    requires_file = models.BooleanField(
        default=True,
        verbose_name='Требуется файл'
    )
    
    allowed_file_types = models.CharField(
        max_length=255,
        default='.pdf,.doc,.docx,.txt,.jpg,.png',
        verbose_name='Разрешенные типы файлов'
    )
    
    max_file_size = models.IntegerField(
        default=10485760,  # 10 MB
        verbose_name='Максимальный размер файла (bytes)'
    )
    
    # Статус
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='draft',
        verbose_name='Статус',
        db_index=True
    )

    # Черновик «заполнить позже» — создан при завершении урока, ментор должен дописать задание
    fill_later = models.BooleanField(
        default=False,
        verbose_name='Заполнить позже',
        db_index=True
    )
    
    # Статистика
    total_submissions = models.IntegerField(
        default=0,
        verbose_name='Всего решений'
    )

    checked_submissions = models.IntegerField(
        default=0,
        verbose_name='Проверено решений'
    )

    returned_submissions = models.IntegerField(
        default=0,
        verbose_name='Возвращено на доработку'
    )
    
    ai_draft_submissions = models.IntegerField(
        default=0,
        verbose_name='Черновиков от ИИ',
        help_text='Количество решений со статусом «ожидает проверки» и заполненным черновиком от ИИ'
    )
    
    average_score = models.FloatField(
        default=0.0,
        verbose_name='Средний балл'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    published_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дата публикации'
    )
    
    class Meta:
        db_table = 'homeworks'
        verbose_name = 'Домашнее задание'
        verbose_name_plural = 'Домашние задания'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['mentor', 'status']),
            models.Index(fields=['lesson']),
            models.Index(fields=['deadline']),
            models.Index(fields=['status', 'published_at']),
            models.Index(fields=['mentor', 'created_at']),
            models.Index(fields=['status', 'deadline']),
        ]
    
    def __str__(self):
        return self.title
    
    def publish(self):
        """Опубликовать задание."""
        if self.status != 'published':
            self.status = 'published'
            self.published_at = timezone.now()
            self.save()
    
    def archive(self):
        """Архивировать задание."""
        self.status = 'archived'
        self.save()
    
    def is_overdue(self):
        """Проверка просрочено ли задание."""
        if self.deadline:
            return timezone.now() > self.deadline
        return False
    
    def update_statistics(self):
        """Обновить статистику задания."""
        submissions = self.submissions.all()
        self.total_submissions = submissions.count()
        self.checked_submissions = submissions.filter(status='graded').count()
        self.returned_submissions = submissions.filter(status='returned').count()
        self.ai_draft_submissions = submissions.filter(
            status='pending'
        ).exclude(ai_checked_at__isnull=True).count()

        graded = submissions.filter(status='graded')
        if graded.exists():
            self.average_score = graded.aggregate(
                avg=models.Avg('score')
            )['avg'] or 0.0
        else:
            self.average_score = 0.0

        self.save(update_fields=[
            'total_submissions',
            'checked_submissions',
            'returned_submissions',
            'ai_draft_submissions',
            'average_score'
        ])


def assignment_file_upload_path(instance, filename):
    """Путь для загрузки файлов задания (одно назначение — только задание)."""
    ext = filename.split('.')[-1] if '.' in filename else ''
    name = f"{uuid.uuid4()}.{ext}" if ext else str(uuid.uuid4())
    return os.path.join('homework', 'assignment_files', str(instance.homework_id), name)


class HomeworkAssignmentFile(models.Model):
    """
    Файл задания: прямая связь Homework → файл.
    Только для файлов, прикреплённых ментором к заданию (без file_type, без submission).
    """
    homework = models.ForeignKey(
        Homework,
        on_delete=models.CASCADE,
        related_name='assignment_files',
        verbose_name='Домашнее задание',
    )
    file = models.FileField(
        upload_to=assignment_file_upload_path,
        max_length=500,
        verbose_name='Файл',
    )
    filename = models.CharField(
        max_length=255,
        verbose_name='Название файла',
    )
    file_size = models.BigIntegerField(
        verbose_name='Размер файла (bytes)',
    )
    uploaded_by = models.ForeignKey(
        'users.User',
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='uploaded_assignment_files',
        verbose_name='Загрузил',
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата загрузки',
    )

    class Meta:
        db_table = 'homework_assignment_files'
        verbose_name = 'Файл задания'
        verbose_name_plural = 'Файлы задания'
        ordering = ['created_at']

    def __str__(self):
        return self.filename


class HomeworkSubmission(models.Model):
    """
    Модель решения домашнего задания.
    """
    
    STATUS_CHOICES = [
        ('pending', 'Ожидает проверки'),
        ('checking', 'На проверке'),
        ('graded', 'Проверено'),
        ('returned', 'Возвращено на доработку'),
    ]
    
    # Основная информация
    homework = models.ForeignKey(
        Homework,
        on_delete=models.CASCADE,
        related_name='submissions',
        verbose_name='Домашнее задание'
    )
    
    student = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='homework_submissions',
        verbose_name='Студент'
    )
    
    # Содержимое решения
    content = models.TextField(
        blank=True,
        verbose_name='Текст решения'
    )
    
    attachment = models.FileField(
        upload_to=submission_file_upload_path,
        blank=True,
        max_length=500,
        verbose_name='Файл решения'
    )
    
    attachment_url = models.URLField(
        blank=True,
        max_length=500,
        verbose_name='Ссылка на решение'
    )
    
    # Статус и проверка
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='pending',
        verbose_name='Статус',
        db_index=True
    )
    
    score = models.IntegerField(
        null=True,
        blank=True,
        validators=[MinValueValidator(0)],
        verbose_name='Балл'
    )
    
    passed = models.BooleanField(
        default=False,
        verbose_name='Сдано'
    )
    
    # Отзыв ментора
    feedback = models.TextField(
        blank=True,
        verbose_name='Отзыв'
    )
    
    checked_by = models.ForeignKey(
        'users.User',
        on_delete=models.SET_NULL,
        related_name='checked_submissions',
        null=True,
        blank=True,
        verbose_name='Проверил'
    )
    
    checked_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дата проверки'
    )
    
    # AI проверка
    ai_score = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='AI балл'
    )
    
    ai_feedback = models.TextField(
        blank=True,
        verbose_name='AI отзыв'
    )
    
    ai_checked_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дата AI проверки'
    )
    
    graded_by_ai = models.BooleanField(
        default=False,
        verbose_name='Оценку выставил ИИ',
        help_text='True, если оценка опубликована автоматически через ИИ'
    )
    
    # Попытки
    attempt_number = models.IntegerField(
        default=1,
        verbose_name='Номер попытки'
    )
    
    is_late = models.BooleanField(
        default=False,
        verbose_name='Сдано с опозданием'
    )
    
    # Временные метки
    submitted_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата отправки'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'homework_submissions'
        verbose_name = 'Решение ДЗ'
        verbose_name_plural = 'Решения ДЗ'
        ordering = ['-submitted_at']
        unique_together = ['homework', 'student', 'attempt_number']
        indexes = [
            models.Index(fields=['homework', 'student']),
            models.Index(fields=['student', 'status']),
            models.Index(fields=['status', 'submitted_at']),
            models.Index(fields=['homework', 'status']),
            models.Index(fields=['submitted_at']),
        ]
    
    def __str__(self):
        return f"{self.student.get_full_name()} - {self.homework.title}"
    
    def grade(self, score, feedback, checked_by):
        """Выставить оценку."""
        self.status = 'graded'
        self.score = score
        self.feedback = feedback
        self.checked_by = checked_by
        self.checked_at = timezone.now()
        
        # Проверяем прошло ли
        if score >= self.homework.passing_score:
            self.passed = True
        
        self.save()
        
        # Обновляем статистику задания
        self.homework.update_statistics()
    
    def return_for_revision(self, feedback, checked_by):
        """Вернуть на доработку."""
        self.status = 'returned'
        self.feedback = feedback
        self.checked_by = checked_by
        self.checked_at = timezone.now()
        self.save()

        # Обновляем статистику задания
        self.homework.update_statistics()
    
    def check_if_late(self):
        """Проверить сдано ли с опозданием."""
        if self.homework.deadline:
            if self.submitted_at > self.homework.deadline:
                self.is_late = True
                self.save(update_fields=['is_late'])


class HomeworkFile(models.Model):
    """
    Дополнительные файлы к домашнему заданию или решению.
    """
    
    FILE_TYPE_CHOICES = [
        ('assignment', 'Файл задания'),
        ('submission', 'Файл решения'),
        ('feedback', 'Файл отзыва'),
    ]
    
    homework = models.ForeignKey(
        Homework,
        on_delete=models.CASCADE,
        related_name='files',
        null=True,
        blank=True,
        verbose_name='Домашнее задание'
    )
    
    submission = models.ForeignKey(
        HomeworkSubmission,
        on_delete=models.CASCADE,
        related_name='files',
        null=True,
        blank=True,
        verbose_name='Решение'
    )
    
    file_type = models.CharField(
        max_length=20,
        choices=FILE_TYPE_CHOICES,
        verbose_name='Тип файла'
    )
    
    file = models.FileField(
        upload_to='homework/files/',
        max_length=500,
        verbose_name='Файл'
    )
    
    filename = models.CharField(
        max_length=255,
        verbose_name='Название файла'
    )
    
    file_size = models.BigIntegerField(
        verbose_name='Размер файла (bytes)'
    )
    
    uploaded_by = models.ForeignKey(
        'users.User',
        on_delete=models.SET_NULL,
        related_name='uploaded_homework_files',
        null=True,
        verbose_name='Загрузил'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата загрузки'
    )
    
    class Meta:
        db_table = 'homework_files'
        verbose_name = 'Файл ДЗ'
        verbose_name_plural = 'Файлы ДЗ'
        ordering = ['-created_at']
    
    def __str__(self):
        return self.filename


class HomeworkAIAgent(models.Model):
    """
    ИИ-агент для проверки домашних заданий.
    OpenAI-совместимый API. Рекомендуется RouterAI: https://routerai.ru/docs/reference
    Эндпоинт: POST {base_url}/chat/completions (OpenAI-формат).
    В openai_url храним базовый URL до .../v1 (без /chat/completions).
    """
    name = models.CharField(
        max_length=255,
        verbose_name='Название модели'
    )
    openai_url = models.URLField(
        max_length=500,
        verbose_name='OpenAI URL (базовый)',
        help_text='Базовый URL до .../v1. RouterAI: https://routerai.ru/api/v1'
    )
    model_name = models.CharField(
        max_length=255,
        verbose_name='Название модели',
        help_text='Идентификатор модели RouterAI, например: google/gemini-3-flash-preview, openai/gpt-4o-mini, anthropic/claude-3-5-sonnet. Список: https://routerai.ru/models'
    )
    api_key = models.CharField(
        max_length=2048,
        blank=True,
        verbose_name='API ключ (токен)',
        help_text='API-ключ с https://routerai.ru/settings/keys. Пусто — использовать HOMEWORK_AI_API_KEY из .env'
    )
    AUTH_HEADER_BEARER = 'Bearer'
    AUTH_HEADER_X_API_KEY = 'X-API-Key'
    AUTH_HEADER_CHOICES = [
        (AUTH_HEADER_BEARER, 'Authorization: Bearer (по умолчанию, RouterAI)'),
        (AUTH_HEADER_X_API_KEY, 'X-API-Key'),
    ]
    auth_header = models.CharField(
        max_length=32,
        choices=AUTH_HEADER_CHOICES,
        default=AUTH_HEADER_BEARER,
        verbose_name='Заголовок авторизации',
        help_text='RouterAI использует Bearer. При 401 у другого провайдера попробуйте X-API-Key.'
    )
    system_prompt = models.TextField(
        blank=True,
        default='',
        verbose_name='Системный промпт',
        help_text='Системный промпт для модели (роль и инструкции проверки). Пусто — используется встроенный промпт проверки ДЗ.'
    )
    is_default = models.BooleanField(
        default=False,
        verbose_name='Использовать по умолчанию для проверки ДЗ'
    )
    order = models.PositiveIntegerField(
        default=0,
        verbose_name='Порядок сортировки'
    )
    is_active = models.BooleanField(
        default=True,
        verbose_name='Активен'
    )
    dev_mode = models.BooleanField(
        default=False,
        verbose_name='Режим разработки (AI)',
        help_text='Включить отладочный промпт: ИИ описывает содержимое изображений в комментарии. Выключено — обычная проверка.'
    )
    # Параметры генерации, влияющие на ответ модели (OpenAI/RouterAI chat completions)
    temperature = models.FloatField(
        null=True,
        blank=True,
        validators=[MinValueValidator(0.0), MaxValueValidator(2.0)],
        verbose_name='Temperature',
        help_text='Случайность ответа: 0 = детерминированный, 2 = максимально разнообразный. Обычно 0.3–0.7 для проверки ДЗ. Пусто — значение по умолчанию провайдера.'
    )
    top_p = models.FloatField(
        null=True,
        blank=True,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name='Top P (nucleus sampling)',
        help_text='Доля наиболее вероятных токенов для выбора (0–1). Меньше — более фокусный ответ. Пусто — по умолчанию провайдера.'
    )
    max_tokens = models.PositiveIntegerField(
        null=True,
        blank=True,
        verbose_name='Max output tokens',
        help_text='Максимальная длина ответа в токенах. Пусто — лимит провайдера. Для развёрнутого комментария можно 2000–4000.'
    )
    usage_count = models.PositiveIntegerField(
        default=0,
        verbose_name='Использований',
        help_text='Счётчик успешных проверок ДЗ через этого агента.'
    )
    total_prompt_tokens = models.PositiveBigIntegerField(
        default=0,
        verbose_name='Всего токенов (вход)',
        help_text='Накоплено входящих токенов за все проверки. Баланс и лимиты — в личном кабинете RouterAI.'
    )
    total_completion_tokens = models.PositiveBigIntegerField(
        default=0,
        verbose_name='Всего токенов (выход)',
        help_text='Накоплено исходящих токенов за все проверки.'
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='Создан')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлён')

    class Meta:
        db_table = 'homework_ai_agents'
        verbose_name = 'ИИ-агент для ДЗ'
        verbose_name_plural = 'ИИ-агенты для ДЗ'
        ordering = ['order', 'name']

    def __str__(self):
        return f'{self.name} ({self.model_name})'

    def save(self, *args, **kwargs):
        # Нормализация: убираем /chat/completions, если вставили полный URL из документации
        if self.openai_url:
            url = self.openai_url.rstrip('/')
            if url.endswith('/chat/completions'):
                self.openai_url = url[:-len('/chat/completions')].rstrip('/')
        super().save(*args, **kwargs)

    def get_base_url(self):
        """Базовый URL для OpenAI-клиента (без завершающего слэша)."""
        if not self.openai_url:
            return ''
        url = self.openai_url.rstrip('/')
        if url.endswith('/chat/completions'):
            url = url[:-len('/chat/completions')].rstrip('/')
        return url