"""
Модели для учебных материалов.
"""
from django.db import models
from django.core.validators import MinValueValidator
import uuid
import os
import mimetypes


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


class MaterialFolder(models.Model):
    """
    Папка для организации материалов.
    """
    
    name = models.CharField(
        max_length=255,
        verbose_name='Название'
    )
    
    description = models.TextField(
        blank=True,
        verbose_name='Описание'
    )
    
    owner = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='material_folders',
        verbose_name='Владелец'
    )
    
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        related_name='subfolders',
        null=True,
        blank=True,
        verbose_name='Родительская папка'
    )
    
    # Доступ
    is_public = models.BooleanField(
        default=False,
        verbose_name='Публичная'
    )
    
    shared_with = models.ManyToManyField(
        'users.User',
        related_name='shared_folders',
        blank=True,
        verbose_name='Доступ предоставлен'
    )
    
    # Статистика
    materials_count = models.IntegerField(
        default=0,
        verbose_name='Количество материалов'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'material_folders'
        verbose_name = 'Папка материалов'
        verbose_name_plural = 'Папки материалов'
        ordering = ['name']
        unique_together = ['owner', 'parent', 'name']
        indexes = [
            models.Index(fields=['owner', 'parent']),
            models.Index(fields=['owner', 'is_public']),
        ]
    
    def __str__(self):
        return self.name
    
    def get_path(self):
        """Получить полный путь папки."""
        if self.parent:
            return f"{self.parent.get_path()}/{self.name}"
        return self.name
    
    def update_materials_count(self):
        """Обновить количество материалов."""
        self.materials_count = self.materials.filter(is_deleted=False).count()
        self.save(update_fields=['materials_count'])


class MaterialTag(models.Model):
    """
    Тег для материалов.
    """
    
    name = models.CharField(
        max_length=50,
        unique=True,
        verbose_name='Название'
    )
    
    slug = models.SlugField(
        max_length=50,
        unique=True,
        verbose_name='Слаг'
    )
    
    color = models.CharField(
        max_length=7,
        default='#007bff',
        verbose_name='Цвет'
    )
    
    materials_count = models.IntegerField(
        default=0,
        verbose_name='Количество материалов'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    class Meta:
        db_table = 'material_tags'
        verbose_name = 'Тег материала'
        verbose_name_plural = 'Теги материалов'
        ordering = ['name']
    
    def __str__(self):
        return self.name


class Material(models.Model):
    """
    Модель учебного материала.
    """
    
    TYPE_CHOICES = [
        ('document', 'Документ'),
        ('presentation', 'Презентация'),
        ('video', 'Видео'),
        ('audio', 'Аудио'),
        ('image', 'Изображение'),
        ('archive', 'Архив'),
        ('link', 'Ссылка'),
        ('other', 'Другое'),
    ]
    
    ACCESS_CHOICES = [
        ('private', 'Приватный'),
        ('public', 'Публичный'),
        ('lesson', 'Для занятия'),
        ('clients', 'Для клиентов'),
    ]
    
    # Основная информация
    title = models.CharField(
        max_length=255,
        verbose_name='Название'
    )
    
    description = models.TextField(
        blank=True,
        verbose_name='Описание'
    )
    
    # Файл или ссылка
    file = models.FileField(
        upload_to=material_file_upload_path,
        blank=True,
        max_length=500,
        verbose_name='Файл'
    )
    
    file_name = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Имя файла'
    )
    
    file_size = models.BigIntegerField(
        default=0,
        verbose_name='Размер файла (bytes)'
    )
    
    file_type = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='MIME тип'
    )
    
    url = models.URLField(
        blank=True,
        max_length=500,
        verbose_name='Ссылка'
    )
    
    material_type = models.CharField(
        max_length=20,
        choices=TYPE_CHOICES,
        default='other',
        verbose_name='Тип материала',
        db_index=True
    )
    
    # Владелец и организация
    owner = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='materials',
        verbose_name='Владелец'
    )
    
    folder = models.ForeignKey(
        MaterialFolder,
        on_delete=models.SET_NULL,
        related_name='materials',
        null=True,
        blank=True,
        verbose_name='Папка'
    )
    
    tags = models.ManyToManyField(
        MaterialTag,
        related_name='materials',
        blank=True,
        verbose_name='Теги'
    )
    
    # Связи
    lesson = models.ForeignKey(
        'schedule.Lesson',
        on_delete=models.SET_NULL,
        related_name='materials',
        null=True,
        blank=True,
        verbose_name='Занятие'
    )
    
    homework = models.ForeignKey(
        'homework.Homework',
        on_delete=models.SET_NULL,
        related_name='materials',
        null=True,
        blank=True,
        verbose_name='Домашнее задание'
    )
    
    # Доступ
    access_type = models.CharField(
        max_length=20,
        choices=ACCESS_CHOICES,
        default='private',
        verbose_name='Тип доступа',
        db_index=True
    )
    
    shared_with = models.ManyToManyField(
        'users.User',
        related_name='shared_materials',
        blank=True,
        verbose_name='Доступ предоставлен'
    )
    
    # Настройки
    allow_download = models.BooleanField(
        default=True,
        verbose_name='Разрешить скачивание'
    )
    
    is_featured = models.BooleanField(
        default=False,
        verbose_name='Избранный'
    )
    
    # Статистика
    views_count = models.IntegerField(
        default=0,
        verbose_name='Количество просмотров'
    )
    
    downloads_count = models.IntegerField(
        default=0,
        verbose_name='Количество скачиваний'
    )
    
    # Удаление
    is_deleted = models.BooleanField(
        default=False,
        verbose_name='Удален',
        db_index=True
    )
    
    deleted_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дата удаления'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'materials'
        verbose_name = 'Материал'
        verbose_name_plural = 'Материалы'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['owner', 'is_deleted']),
            models.Index(fields=['folder', 'is_deleted']),
            models.Index(fields=['material_type']),
            models.Index(fields=['access_type', 'is_deleted']),
            models.Index(fields=['lesson']),
            models.Index(fields=['homework']),
            models.Index(fields=['owner', 'created_at']),
            models.Index(fields=['access_type', 'material_type']),
        ]
    
    def __str__(self):
        return self.title
    
    def save(self, *args, **kwargs):
        """Переопределяем save для автоматической обработки."""
        # Определяем тип материала по MIME типу
        if self.file and not self.material_type:
            self.material_type = self.detect_material_type()
        
        # Сохраняем имя файла
        if self.file and not self.file_name:
            self.file_name = os.path.basename(self.file.name)
        
        super().save(*args, **kwargs)
        
        # Обновляем счетчик папки
        if self.folder:
            self.folder.update_materials_count()
    
    def detect_material_type(self):
        """Определить тип материала по MIME типу."""
        if not self.file_type:
            return 'other'
        
        mime = self.file_type.lower()
        
        if mime.startswith('image/'):
            return 'image'
        elif mime.startswith('video/'):
            return 'video'
        elif mime.startswith('audio/'):
            return 'audio'
        elif 'pdf' in mime or 'document' in mime or 'text' in mime:
            return 'document'
        elif 'presentation' in mime or 'powerpoint' in mime:
            return 'presentation'
        elif 'zip' in mime or 'rar' in mime or 'archive' in mime:
            return 'archive'
        
        return 'other'
    
    def increment_views(self):
        """Увеличить счетчик просмотров."""
        self.views_count += 1
        self.save(update_fields=['views_count'])
    
    def increment_downloads(self):
        """Увеличить счетчик скачиваний."""
        self.downloads_count += 1
        self.save(update_fields=['downloads_count'])
    
    def soft_delete(self):
        """Мягкое удаление."""
        from django.utils import timezone
        self.is_deleted = True
        self.deleted_at = timezone.now()
        self.save()
        
        # Обновляем счетчик папки
        if self.folder:
            self.folder.update_materials_count()
    
    def has_access(self, user):
        """Проверка доступа пользователя к материалу."""
        # Владелец всегда имеет доступ
        if self.owner == user:
            return True
        
        # Публичные материалы доступны всем
        if self.access_type == 'public':
            return True
        
        # Доступ предоставлен напрямую
        if self.shared_with.filter(id=user.id).exists():
            return True
        
        # Материалы для клиентов
        if self.access_type == 'clients':
            # Проверяем что пользователь - клиент владельца
            from apps.users.models import Client
            try:
                client = Client.objects.get(user=user)
                if self.owner in client.mentors.all():
                    return True
            except Client.DoesNotExist:
                pass
        
        # Материалы для занятия
        if self.access_type == 'lesson' and self.lesson:
            return user in [self.lesson.mentor, self.lesson.client]
        
        return False


class MaterialAccess(models.Model):
    """
    Лог доступа к материалам.
    """
    
    ACTION_CHOICES = [
        ('view', 'Просмотр'),
        ('download', 'Скачивание'),
        ('share', 'Предоставление доступа'),
    ]
    
    material = models.ForeignKey(
        Material,
        on_delete=models.CASCADE,
        related_name='access_logs',
        verbose_name='Материал'
    )
    
    user = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='material_accesses',
        verbose_name='Пользователь'
    )
    
    action = models.CharField(
        max_length=20,
        choices=ACTION_CHOICES,
        verbose_name='Действие'
    )
    
    ip_address = models.GenericIPAddressField(
        null=True,
        blank=True,
        verbose_name='IP адрес'
    )
    
    user_agent = models.CharField(
        max_length=500,
        blank=True,
        verbose_name='User Agent'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата',
        db_index=True
    )
    
    class Meta:
        db_table = 'material_access_logs'
        verbose_name = 'Лог доступа к материалу'
        verbose_name_plural = 'Логи доступа к материалам'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['material', 'created_at']),
            models.Index(fields=['user', 'created_at']),
        ]
    
    def __str__(self):
        return f"{self.user.email} - {self.get_action_display()} - {self.material.title}"


class StorageQuota(models.Model):
    """
    Квота хранилища для пользователя.
    """
    
    user = models.OneToOneField(
        'users.User',
        on_delete=models.CASCADE,
        related_name='storage_quota',
        verbose_name='Пользователь'
    )
    
    # Лимиты в байтах
    total_quota = models.BigIntegerField(
        default=1073741824,  # 1 GB
        verbose_name='Общая квота (bytes)'
    )
    
    used_space = models.BigIntegerField(
        default=0,
        verbose_name='Использовано (bytes)'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'storage_quotas'
        verbose_name = 'Квота хранилища'
        verbose_name_plural = 'Квоты хранилища'
    
    def __str__(self):
        return f"{self.user.email} - {self.get_used_percentage():.1f}%"
    
    def get_used_percentage(self):
        """Получить процент использования."""
        if self.total_quota == 0:
            return 0
        return (self.used_space / self.total_quota) * 100
    
    def get_available_space(self):
        """Получить доступное пространство."""
        return self.total_quota - self.used_space
    
    def has_space(self, size):
        """Проверить достаточно ли места."""
        return self.get_available_space() >= size
    
    def add_usage(self, size):
        """Добавить использование."""
        self.used_space += size
        self.save(update_fields=['used_space'])
    
    def remove_usage(self, size):
        """Убрать использование."""
        self.used_space = max(0, self.used_space - size)
        self.save(update_fields=['used_space'])
    
    def recalculate(self):
        """Пересчитать использование."""
        total = Material.objects.filter(
            owner=self.user,
            is_deleted=False
        ).aggregate(
            total=models.Sum('file_size')
        )['total'] or 0
        
        self.used_space = total
        self.save(update_fields=['used_space'])
