"""
Модели для системы чата и сообщений.
"""
from django.db import models
from django.utils import timezone
import uuid
import os


def message_file_upload_path(instance, filename):
    """Путь для загрузки файлов сообщений."""
    ext = filename.split('.')[-1]
    new_filename = f"{uuid.uuid4()}.{ext}"
    return os.path.join('file_chat', str(instance.message.chat.id), new_filename)


class Chat(models.Model):
    """
    Модель чата.
    """
    
    CHAT_TYPE_CHOICES = [
        ('direct', 'Личный'),
        ('group', 'Групповой'),
    ]
    
    # Основная информация
    uuid = models.UUIDField(
        default=uuid.uuid4,
        unique=True,
        editable=False,
        verbose_name='UUID'
    )
    
    chat_type = models.CharField(
        max_length=20,
        choices=CHAT_TYPE_CHOICES,
        default='direct',
        verbose_name='Тип чата',
        db_index=True
    )
    
    name = models.CharField(
        max_length=255,
        blank=True,
        verbose_name='Название'
    )
    
    description = models.TextField(
        blank=True,
        verbose_name='Описание'
    )
    
    avatar = models.ImageField(
        upload_to='chat/avatars/',
        blank=True,
        null=True,
        verbose_name='Аватар'
    )
    
    # Создатель
    created_by = models.ForeignKey(
        'users.User',
        on_delete=models.SET_NULL,
        related_name='created_chats',
        null=True,
        verbose_name='Создатель'
    )
    
    # Связь с занятием (опционально)
    lesson = models.ForeignKey(
        'schedule.Lesson',
        on_delete=models.SET_NULL,
        related_name='chats',
        null=True,
        blank=True,
        verbose_name='Занятие'
    )
    
    # Статистика
    messages_count = models.IntegerField(
        default=0,
        verbose_name='Количество сообщений'
    )
    
    last_message_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Последнее сообщение',
        db_index=True
    )
    
    # Настройки
    is_archived = models.BooleanField(
        default=False,
        verbose_name='Архивирован',
        db_index=True
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'chats'
        verbose_name = 'Чат'
        verbose_name_plural = 'Чаты'
        ordering = ['-last_message_at', '-created_at']
        indexes = [
            models.Index(fields=['chat_type']),
            models.Index(fields=['is_archived']),
            models.Index(fields=['last_message_at']),
        ]
    
    def __str__(self):
        if self.name:
            return self.name
        return f"Чат {self.uuid}"
    
    def update_last_message(self):
        """Обновить время последнего сообщения."""
        self.last_message_at = timezone.now()
        self.save(update_fields=['last_message_at'])
    
    def increment_messages_count(self):
        """Увеличить счетчик сообщений."""
        self.messages_count += 1
        self.save(update_fields=['messages_count'])
    
    def get_participants_ids(self):
        """Получить ID участников чата."""
        return list(self.participants.values_list('user_id', flat=True))


class ChatParticipant(models.Model):
    """
    Модель участника чата.
    """
    
    ROLE_CHOICES = [
        ('admin', 'Администратор'),
        ('member', 'Участник'),
    ]
    
    chat = models.ForeignKey(
        Chat,
        on_delete=models.CASCADE,
        related_name='participants',
        verbose_name='Чат'
    )
    
    user = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='chat_participations',
        verbose_name='Пользователь'
    )
    
    role = models.CharField(
        max_length=20,
        choices=ROLE_CHOICES,
        default='member',
        verbose_name='Роль'
    )
    
    # Статистика
    unread_count = models.IntegerField(
        default=0,
        verbose_name='Непрочитанных'
    )
    
    last_read_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Последнее прочтение'
    )
    
    # Настройки
    is_muted = models.BooleanField(
        default=False,
        verbose_name='Уведомления отключены'
    )
    
    is_pinned = models.BooleanField(
        default=False,
        verbose_name='Закреплен'
    )
    
    # Временные метки
    joined_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата присоединения'
    )
    
    left_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Дата выхода'
    )
    
    class Meta:
        db_table = 'chat_participants'
        verbose_name = 'Участник чата'
        verbose_name_plural = 'Участники чата'
        unique_together = ['chat', 'user']
        ordering = ['-joined_at']
        indexes = [
            models.Index(fields=['user', 'chat']),
            models.Index(fields=['chat', 'user']),
        ]
    
    def __str__(self):
        return f"{self.user.email} в {self.chat}"
    
    def mark_as_read(self):
        """Отметить все сообщения как прочитанные."""
        self.unread_count = 0
        self.last_read_at = timezone.now()
        self.save()
    
    def increment_unread(self):
        """Увеличить счетчик непрочитанных."""
        self.unread_count += 1
        self.save(update_fields=['unread_count'])


class Message(models.Model):
    """
    Модель сообщения.
    """
    
    MESSAGE_TYPE_CHOICES = [
        ('text', 'Текст'),
        ('file', 'Файл'),
        ('image', 'Изображение'),
        ('video', 'Видео'),
        ('audio', 'Аудио'),
        ('system', 'Системное'),
    ]
    
    # Основная информация
    uuid = models.UUIDField(
        default=uuid.uuid4,
        unique=True,
        editable=False,
        verbose_name='UUID'
    )
    
    chat = models.ForeignKey(
        Chat,
        on_delete=models.CASCADE,
        related_name='messages',
        verbose_name='Чат'
    )
    
    sender = models.ForeignKey(
        'users.User',
        on_delete=models.SET_NULL,
        related_name='sent_messages',
        null=True,
        verbose_name='Отправитель'
    )
    
    message_type = models.CharField(
        max_length=20,
        choices=MESSAGE_TYPE_CHOICES,
        default='text',
        verbose_name='Тип сообщения'
    )
    
    # Контент
    content = models.TextField(
        verbose_name='Содержимое'
    )
    
    # Ответ на сообщение
    reply_to = models.ForeignKey(
        'self',
        on_delete=models.SET_NULL,
        related_name='replies',
        null=True,
        blank=True,
        verbose_name='Ответ на'
    )
    
    # Редактирование
    is_edited = models.BooleanField(
        default=False,
        verbose_name='Отредактировано'
    )
    
    edited_at = models.DateTimeField(
        null=True,
        blank=True,
        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='Дата отправки',
        db_index=True
    )
    
    class Meta:
        db_table = 'messages'
        verbose_name = 'Сообщение'
        verbose_name_plural = 'Сообщения'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['chat', 'created_at']),
            models.Index(fields=['sender']),
            models.Index(fields=['is_deleted']),
        ]
    
    def __str__(self):
        preview = self.content[:50] if len(self.content) > 50 else self.content
        return f"{self.sender.email if self.sender else 'System'}: {preview}"
    
    def save(self, *args, **kwargs):
        """Переопределяем save."""
        is_new = self.pk is None
        
        super().save(*args, **kwargs)
        
        # При создании нового сообщения
        if is_new:
            # Обновляем счетчик и время последнего сообщения в чате
            self.chat.increment_messages_count()
            self.chat.update_last_message()
            
            # Системные сообщения (уведомления) не увеличивают счётчик непрочитанных — уведомления есть отдельно
            if self.message_type != 'system':
                # Увеличиваем счетчик непрочитанных для всех участников кроме отправителя
                participants = list(self.chat.participants.exclude(user=self.sender))
                for participant in participants:
                    participant.unread_count += 1
                if participants:
                    ChatParticipant.objects.bulk_update(participants, ['unread_count'])
    
    def mark_as_edited(self):
        """Отметить как отредактированное."""
        self.is_edited = True
        self.edited_at = timezone.now()
        self.save()
    
    def soft_delete(self):
        """Мягкое удаление."""
        self.is_deleted = True
        self.deleted_at = timezone.now()
        self.save()


class MessageFile(models.Model):
    """
    Модель файла сообщения.
    """
    
    message = models.ForeignKey(
        Message,
        on_delete=models.CASCADE,
        related_name='files',
        verbose_name='Сообщение'
    )
    
    file = models.FileField(
        upload_to=lambda instance, filename: os.path.join('file_chat', str(instance.message.chat.id), filename),
        max_length=500,
        verbose_name='Файл'
    )
    
    file_name = models.CharField(
        max_length=255,
        verbose_name='Имя файла'
    )
    
    file_size = models.BigIntegerField(
        verbose_name='Размер файла (bytes)'
    )
    
    file_type = models.CharField(
        max_length=100,
        verbose_name='MIME тип'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата загрузки'
    )
    
    class Meta:
        db_table = 'message_files'
        verbose_name = 'Файл сообщения'
        verbose_name_plural = 'Файлы сообщений'
        ordering = ['created_at']
    
    def __str__(self):
        return f"{self.file_name} ({self.message.uuid})"


class MessageRead(models.Model):
    """
    Модель прочтения сообщений.
    Отслеживает кто и когда прочитал сообщение.
    """
    
    message = models.ForeignKey(
        Message,
        on_delete=models.CASCADE,
        related_name='reads',
        verbose_name='Сообщение'
    )
    
    user = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='message_reads',
        verbose_name='Пользователь'
    )
    
    read_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата прочтения',
        db_index=True
    )
    
    class Meta:
        db_table = 'message_reads'
        verbose_name = 'Прочтение сообщения'
        verbose_name_plural = 'Прочтения сообщений'
        unique_together = ['message', 'user']
        ordering = ['-read_at']
        indexes = [
            models.Index(fields=['message', 'user']),
            models.Index(fields=['user', 'read_at']),
        ]
    
    def __str__(self):
        return f"{self.user.email} прочитал {self.message.uuid}"


class MessageReaction(models.Model):
    """
    Модель реакции на сообщение.
    """
    
    message = models.ForeignKey(
        Message,
        on_delete=models.CASCADE,
        related_name='reactions',
        verbose_name='Сообщение'
    )
    
    user = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='message_reactions',
        verbose_name='Пользователь'
    )
    
    emoji = models.CharField(
        max_length=10,
        verbose_name='Эмодзи'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата',
        db_index=True
    )
    
    class Meta:
        db_table = 'message_reactions'
        verbose_name = 'Реакция на сообщение'
        verbose_name_plural = 'Реакции на сообщения'
        unique_together = ['message', 'user', 'emoji']
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['message']),
            models.Index(fields=['user']),
        ]
    
    def __str__(self):
        return f"{self.user.email} - {self.emoji}"
