"""
Модели для видеоконференций.
"""
from django.db import models
from django.utils import timezone
from datetime import timedelta
import uuid
import secrets


class VideoRoom(models.Model):
    """
    Модель видеокомнаты.
    Представляет виртуальную комнату для видеоконференции.
    """
    
    STATUS_CHOICES = [
        ('waiting', 'Ожидание'),
        ('active', 'Активна'),
        ('ended', 'Завершена'),
    ]
    
    SFU_TYPE_CHOICES = [
        ('ion-sfu', 'Ion SFU'),
        ('janus', 'Janus Gateway'),
    ]
    
    # Уникальный идентификатор комнаты
    room_id = models.UUIDField(
        default=uuid.uuid4,
        unique=True,
        editable=False,
        verbose_name='ID комнаты'
    )
    
    sfu_type = models.CharField(
        max_length=20,
        choices=SFU_TYPE_CHOICES,
        default='ion-sfu',
        verbose_name='Тип SFU',
        help_text='Используемый SFU сервер (ion-sfu или janus)'
    )
    
    # Токен доступа для входа в комнату
    access_token = models.CharField(
        max_length=64,
        unique=True,
        db_index=True,
        blank=True,
        verbose_name='Токен доступа',
        help_text='Уникальный токен для входа в видеокомнату'
    )
    
    # Связь с занятием
    lesson = models.OneToOneField(
        'schedule.Lesson',
        on_delete=models.CASCADE,
        related_name='video_room',
        verbose_name='Занятие'
    )
    
    # Участники
    mentor = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='mentor_video_rooms',
        limit_choices_to={'role': 'mentor'},
        verbose_name='Ментор'
    )
    
    client = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='client_video_rooms',
        verbose_name='Клиент'
    )
    
    # Статус
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='waiting',
        verbose_name='Статус',
        db_index=True
    )
    
    # Время
    started_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Время начала'
    )
    
    ended_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Время окончания'
    )
    
    duration = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Длительность (секунды)',
        help_text='Фактическая длительность видеозвонка'
    )
    
    # Настройки
    is_recording = models.BooleanField(
        default=False,
        verbose_name='Запись включена'
    )
    
    recording_url = models.URLField(
        blank=True,
        max_length=500,
        verbose_name='Ссылка на запись'
    )
    
    # Mediasoup router ID (для управления)
    router_id = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Mediasoup Router ID'
    )
    
    # Статистика
    mentor_joined_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Ментор подключился'
    )
    
    client_joined_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Клиент подключился'
    )
    
    max_participants = models.IntegerField(
        default=2,
        verbose_name='Максимум участников'
    )
    
    # Качество связи
    quality_rating = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Оценка качества связи',
        help_text='От 1 до 5'
    )
    
    quality_issues = models.TextField(
        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 = 'video_rooms'
        verbose_name = 'Видеокомната'
        verbose_name_plural = 'Видеокомнаты'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['room_id']),
            models.Index(fields=['mentor', 'status']),
            models.Index(fields=['client', 'status']),
            models.Index(fields=['status', 'created_at']),
        ]
    
    def __str__(self):
        return f"Комната {self.room_id} - {self.lesson.title}"
    
    def save(self, *args, **kwargs):
        """Генерируем токен доступа при создании комнаты"""
        if not self.access_token or self.access_token == '':
            self.access_token = secrets.token_urlsafe(32)
        super().save(*args, **kwargs)
    
    def get_join_url(self, request=None):
        """Получить URL для входа в комнату (на фронтенд)"""
        # Всегда возвращаем URL фронтенда (порт 3000), а не бэкенда
        from django.conf import settings
        frontend_url = getattr(settings, 'FRONTEND_URL', 'http://localhost:3000')
        
        # Для всех типов (Janus, ion-sfu) используем общий путь
        return f"{frontend_url}/video/join/{self.access_token}"
    
    def start(self):
        """Начать видеозвонок."""
        if self.status != 'waiting':
            raise ValueError('Комната уже начата или завершена')
        
        self.status = 'active'
        self.started_at = timezone.now()
        self.save()
    
    def end(self):
        """Завершить видеозвонок."""
        if self.status != 'active':
            raise ValueError('Комната не активна')
        
        self.status = 'ended'
        self.ended_at = timezone.now()
        
        # Вычисляем длительность
        if self.started_at:
            self.duration = int((self.ended_at - self.started_at).total_seconds())
        
        self.save()
    
    def mark_participant_joined(self, user):
        """Отметить что участник подключился (также обновляет Lesson для метрик)."""
        now = timezone.now()
        update_fields = []
        user_pk = getattr(user, 'pk', None) or getattr(user, 'id', None)
        if user_pk is not None and user_pk == self.mentor_id:
            self.mentor_joined_at = now
            update_fields.append('mentor_joined_at')
        elif user_pk is not None and user_pk == self.client_id:
            self.client_joined_at = now
            update_fields.append('client_joined_at')

        if update_fields:
            self.save(update_fields=update_fields)
            # Синхронизируем метрики на занятие для аналитики
            lesson = self.lesson
            if user_pk == self.mentor_id and not lesson.mentor_connected_at:
                lesson.mentor_connected_at = now
                lesson.save(update_fields=['mentor_connected_at'])
            elif user_pk == self.client_id and not lesson.client_connected_at:
                lesson.client_connected_at = now
                lesson.save(update_fields=['client_connected_at'])
    
    @property
    def is_active(self):
        """Проверка активна ли комната."""
        return self.status == 'active'
    
    @property
    def both_joined(self):
        """Проверка подключились ли оба участника."""
        return self.mentor_joined_at is not None and self.client_joined_at is not None
    
    @property
    def actual_duration(self):
        """Получить фактическую длительность."""
        if self.duration:
            return self.duration
        
        if self.started_at:
            if self.ended_at:
                return int((self.ended_at - self.started_at).total_seconds())
            elif self.is_active:
                return int((timezone.now() - self.started_at).total_seconds())
        
        return 0


class VideoParticipant(models.Model):
    """
    Модель участника видеозвонка.
    Хранит информацию о подключении участника.
    """
    
    room = models.ForeignKey(
        VideoRoom,
        on_delete=models.CASCADE,
        related_name='participants',
        verbose_name='Комната'
    )
    
    user = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='video_participations',
        verbose_name='Пользователь'
    )
    
    # WebSocket connection ID
    connection_id = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Connection ID'
    )
    
    # Mediasoup transport IDs
    send_transport_id = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Send Transport ID'
    )
    
    recv_transport_id = models.CharField(
        max_length=100,
        blank=True,
        verbose_name='Receive Transport ID'
    )
    
    # Статус участия
    is_connected = models.BooleanField(
        default=False,
        verbose_name='Подключен'
    )
    
    is_audio_enabled = models.BooleanField(
        default=True,
        verbose_name='Аудио включено'
    )
    
    is_video_enabled = models.BooleanField(
        default=True,
        verbose_name='Видео включено'
    )
    
    is_screen_sharing = 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='Время отключения'
    )
    
    # Статистика
    total_duration = models.IntegerField(
        default=0,
        verbose_name='Общее время (секунды)'
    )
    
    reconnection_count = models.IntegerField(
        default=0,
        verbose_name='Количество переподключений'
    )
    
    class Meta:
        db_table = 'video_participants'
        verbose_name = 'Участник видео'
        verbose_name_plural = 'Участники видео'
        ordering = ['joined_at']
        unique_together = ['room', 'user']
    
    def __str__(self):
        return f"{self.user.email} в комнате {self.room.room_id}"
    
    def disconnect(self):
        """Отключить участника."""
        self.is_connected = False
        self.left_at = timezone.now()
        
        # Обновляем общее время
        if self.joined_at:
            duration = (self.left_at - self.joined_at).total_seconds()
            self.total_duration += int(duration)
        
        self.save()


class VideoCallLog(models.Model):
    """
    Лог видеозвонка.
    Хранит детальную информацию о звонке для аналитики.
    """
    
    room = models.ForeignKey(
        VideoRoom,
        on_delete=models.CASCADE,
        related_name='call_logs',
        verbose_name='Комната'
    )
    
    # Информация о звонке
    total_participants = models.IntegerField(
        default=0,
        verbose_name='Всего участников'
    )
    
    total_duration = models.IntegerField(
        default=0,
        verbose_name='Общая длительность (секунды)'
    )
    
    # Качество
    average_bitrate = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Средний битрейт (kbps)'
    )
    
    packet_loss_rate = models.FloatField(
        null=True,
        blank=True,
        verbose_name='Процент потери пакетов'
    )
    
    average_jitter = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Средний jitter (ms)'
    )
    
    # Проблемы
    connection_issues = models.IntegerField(
        default=0,
        verbose_name='Проблем с подключением'
    )
    
    audio_issues = models.IntegerField(
        default=0,
        verbose_name='Проблем с аудио'
    )
    
    video_issues = models.IntegerField(
        default=0,
        verbose_name='Проблем с видео'
    )
    
    # Дополнительная информация (JSON)
    metadata = models.JSONField(
        default=dict,
        blank=True,
        verbose_name='Метаданные'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    class Meta:
        db_table = 'video_call_logs'
        verbose_name = 'Лог видеозвонка'
        verbose_name_plural = 'Логи видеозвонков'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"Лог звонка {self.room.room_id}"


class ScreenRecording(models.Model):
    """
    Модель записи экрана/видео.
    Хранит информацию о записях занятий.
    """
    
    STATUS_CHOICES = [
        ('processing', 'Обработка'),
        ('ready', 'Готово'),
        ('failed', 'Ошибка'),
    ]
    
    room = models.ForeignKey(
        VideoRoom,
        on_delete=models.CASCADE,
        related_name='recordings',
        verbose_name='Комната'
    )
    
    # Файл записи
    file_path = models.CharField(
        max_length=500,
        blank=True,
        verbose_name='Путь к файлу'
    )
    
    file_size = models.BigIntegerField(
        null=True,
        blank=True,
        verbose_name='Размер файла (bytes)'
    )
    
    duration = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Длительность (секунды)'
    )
    
    # URL для просмотра
    url = models.URLField(
        blank=True,
        max_length=500,
        verbose_name='URL записи'
    )
    
    # Статус обработки
    status = models.CharField(
        max_length=20,
        choices=STATUS_CHOICES,
        default='processing',
        verbose_name='Статус'
    )
    
    processing_error = models.TextField(
        blank=True,
        verbose_name='Ошибка обработки'
    )
    
    # Доступ
    is_public = models.BooleanField(
        default=False,
        verbose_name='Публичная'
    )
    
    expires_at = models.DateTimeField(
        null=True,
        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='Дата обработки'
    )
    
    class Meta:
        db_table = 'screen_recordings'
        verbose_name = 'Запись видео'
        verbose_name_plural = 'Записи видео'
        ordering = ['-created_at']
    
    def __str__(self):
        return f"Запись {self.room.room_id}"
    
    def mark_as_ready(self):
        """Отметить запись как готовую."""
        self.status = 'ready'
        self.processed_at = timezone.now()
        self.save()
    
    def mark_as_failed(self, error):
        """Отметить запись как ошибочную."""
        self.status = 'failed'
        self.processing_error = str(error)
        self.processed_at = timezone.now()
        self.save()
    
    @property
    def is_expired(self):
        """Проверка истекла ли запись."""
        if self.expires_at:
            return timezone.now() > self.expires_at
        return False
