"""
Модели уведомлений.
"""
from django.db import models
from django.utils import timezone
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType


class PushSubscription(models.Model):
    """
    Модель для хранения Push Notification subscriptions.
    Используется для отправки push уведомлений в браузер.
    """
    user = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='push_subscriptions',
        verbose_name='Пользователь'
    )
    
    subscription_data = models.JSONField(
        verbose_name='Данные subscription',
        help_text='JSON с данными subscription от браузера'
    )
    
    user_agent = models.CharField(
        max_length=500,
        blank=True,
        verbose_name='User Agent',
        help_text='Браузер пользователя'
    )
    
    is_active = models.BooleanField(
        default=True,
        verbose_name='Активна'
    )
    
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        verbose_name = 'Push Subscription'
        verbose_name_plural = 'Push Subscriptions'
        ordering = ['-created_at']
        # Один пользователь может иметь несколько subscriptions (разные устройства/браузеры)
        unique_together = []
    
    def __str__(self):
        return f"Push subscription для {self.user.email}"


class Notification(models.Model):
    """
    Модель уведомления.
    Универсальная модель для всех типов уведомлений.
    """
    
    TYPE_CHOICES = [
        ('lesson_created', 'Создано занятие'),
        ('lesson_updated', 'Занятие обновлено'),
        ('lesson_cancelled', 'Занятие отменено'),
        ('lesson_rescheduled', 'Занятие перенесено'),
        ('lesson_reminder', 'Напоминание о занятии'),
        ('lesson_started', 'Занятие началось'),
        ('lesson_completed', 'Занятие завершено'),
        ('homework_assigned', 'Назначено домашнее задание'),
        ('homework_submitted', 'ДЗ сдано'),
        ('homework_reviewed', 'ДЗ проверено'),
        ('homework_returned', 'ДЗ возвращено на доработку'),
        ('homework_deadline_reminder', 'Напоминание о дедлайне ДЗ'),
        ('homework_overdue', 'ДЗ просрочено'),
        ('material_added', 'Добавлен материал'),
        ('message_received', 'Новое сообщение'),
        ('subscription_expiring', 'Подписка истекает'),
        ('subscription_expired', 'Подписка истекла'),
        ('payment_received', 'Платеж получен'),
        ('mentorship_request_new', 'Новый запрос на менторство'),
        ('mentorship_request_accepted', 'Запрос на менторство принят'),
        ('mentorship_request_rejected', 'Запрос на менторство отклонён'),
        ('mentor_invitation_new', 'Приглашение от ментора'),
        ('mentor_invitation_accepted', 'Приглашение принято студентом'),
        ('mentor_invitation_rejected', 'Приглашение отклонено студентом'),
        ('system', 'Системное уведомление'),
    ]
    
    CHANNEL_CHOICES = [
        ('in_app', 'Внутри приложения'),
        ('email', 'Email'),
        ('telegram', 'Telegram'),
    ]
    
    PRIORITY_CHOICES = [
        ('low', 'Низкий'),
        ('normal', 'Обычный'),
        ('high', 'Высокий'),
        ('urgent', 'Срочный'),
    ]
    
    # Получатель
    recipient = models.ForeignKey(
        'users.User',
        on_delete=models.CASCADE,
        related_name='notifications',
        verbose_name='Получатель'
    )
    
    # Тип и канал
    notification_type = models.CharField(
        max_length=50,
        choices=TYPE_CHOICES,
        verbose_name='Тип уведомления',
        db_index=True
    )
    
    channel = models.CharField(
        max_length=20,
        choices=CHANNEL_CHOICES,
        default='in_app',
        verbose_name='Канал отправки'
    )
    
    priority = models.CharField(
        max_length=20,
        choices=PRIORITY_CHOICES,
        default='normal',
        verbose_name='Приоритет'
    )
    
    # Содержание
    title = models.CharField(
        max_length=200,
        verbose_name='Заголовок'
    )
    
    message = models.TextField(
        verbose_name='Сообщение'
    )
    
    # Дополнительные данные (JSON)
    data = models.JSONField(
        default=dict,
        blank=True,
        verbose_name='Дополнительные данные',
        help_text='Дополнительная информация в формате JSON'
    )
    
    # Связь с объектом (generic relation)
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        verbose_name='Тип объекта'
    )
    
    object_id = models.PositiveIntegerField(
        null=True,
        blank=True,
        verbose_name='ID объекта'
    )
    
    content_object = GenericForeignKey('content_type', 'object_id')
    
    # Ссылка для действия
    action_url = models.CharField(
        max_length=500,
        blank=True,
        verbose_name='Ссылка для действия',
        help_text='URL для перехода при клике на уведомление'
    )
    
    # Статус прочтения
    is_read = models.BooleanField(
        default=False,
        verbose_name='Прочитано',
        db_index=True
    )
    
    read_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Время прочтения'
    )
    
    # Статус отправки
    is_sent = models.BooleanField(
        default=False,
        verbose_name='Отправлено'
    )
    
    sent_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Время отправки'
    )
    
    send_error = models.TextField(
        blank=True,
        verbose_name='Ошибка отправки'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания',
        db_index=True
    )
    
    scheduled_for = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Запланировано на',
        help_text='Время когда нужно отправить уведомление'
    )
    
    expires_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name='Истекает',
        help_text='После этого времени уведомление неактуально'
    )
    
    class Meta:
        db_table = 'notifications'
        verbose_name = 'Уведомление'
        verbose_name_plural = 'Уведомления'
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['recipient', '-created_at']),
            models.Index(fields=['recipient', 'is_read']),
            models.Index(fields=['notification_type', 'created_at']),
            models.Index(fields=['is_sent', 'scheduled_for']),
        ]
    
    def __str__(self):
        return f"{self.get_notification_type_display()} для {self.recipient.email}"
    
    def mark_as_read(self):
        """Отметить как прочитанное."""
        if not self.is_read:
            self.is_read = True
            self.read_at = timezone.now()
            self.save(update_fields=['is_read', 'read_at'])
            # Очищаем кеш дашборда для обновления счетчика непрочитанных уведомлений
            from django.core.cache import cache
            cache_key = f'mentor_dashboard_{self.recipient.id}'
            cache.delete(cache_key)
            # Также очищаем кеш для клиента и родителя, если они есть
            cache.delete(f'client_dashboard_{self.recipient.id}')
            cache.delete(f'parent_dashboard_{self.recipient.id}')
    
    def mark_as_sent(self, error=None):
        """Отметить как отправленное."""
        self.is_sent = True if error is None else False
        self.sent_at = timezone.now()
        if error:
            self.send_error = str(error)
        self.save(update_fields=['is_sent', 'sent_at', 'send_error'])
    
    @property
    def is_expired(self):
        """Проверка истекло ли уведомление."""
        if self.expires_at:
            return timezone.now() > self.expires_at
        return False
    
    @classmethod
    def create_notification(cls, recipient, notification_type, title, message, 
                           channel='in_app', priority='normal', **kwargs):
        """
        Удобный метод для создания уведомления.
        
        Args:
            recipient: Получатель (User)
            notification_type: Тип уведомления
            title: Заголовок
            message: Сообщение
            channel: Канал отправки
            priority: Приоритет
            **kwargs: Дополнительные параметры (data, action_url, content_object и т.д.)
        """
        return cls.objects.create(
            recipient=recipient,
            notification_type=notification_type,
            title=title,
            message=message,
            channel=channel,
            priority=priority,
            **kwargs
        )


class NotificationPreference(models.Model):
    """
    Настройки уведомлений пользователя.
    Определяет какие типы уведомлений и через какие каналы получать.
    """
    
    user = models.OneToOneField(
        'users.User',
        on_delete=models.CASCADE,
        related_name='notification_preferences',
        verbose_name='Пользователь'
    )
    
    # Глобальные настройки
    enabled = models.BooleanField(
        default=True,
        verbose_name='Уведомления включены'
    )
    
    # Каналы
    email_enabled = models.BooleanField(
        default=True,
        verbose_name='Email уведомления'
    )
    
    telegram_enabled = models.BooleanField(
        default=False,
        verbose_name='Telegram уведомления'
    )
    
    in_app_enabled = models.BooleanField(
        default=True,
        verbose_name='Внутренние уведомления'
    )
    
    # Настройки по типам (JSON)
    type_preferences = models.JSONField(
        default=dict,
        blank=True,
        verbose_name='Настройки по типам',
        help_text='Настройки для каждого типа уведомлений'
    )
    
    # Время тишины (не отправлять уведомления)
    quiet_hours_enabled = models.BooleanField(
        default=False,
        verbose_name='Режим тишины включен'
    )
    
    quiet_hours_start = models.TimeField(
        null=True,
        blank=True,
        verbose_name='Начало режима тишины'
    )
    
    quiet_hours_end = models.TimeField(
        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 = 'notification_preferences'
        verbose_name = 'Настройки уведомлений'
        verbose_name_plural = 'Настройки уведомлений'
    
    def __str__(self):
        return f"Настройки уведомлений: {self.user.email}"
    
    def is_type_enabled(self, notification_type, channel='in_app'):
        """Проверка включен ли тип уведомления для канала."""
        if not self.enabled:
            return False
        
        # Проверка канала
        if channel == 'email' and not self.email_enabled:
            return False
        if channel == 'telegram' and not self.telegram_enabled:
            return False
        if channel == 'in_app' and not self.in_app_enabled:
            return False
        
        # Проверка специфичных настроек типа
        if notification_type in self.type_preferences:
            type_settings = self.type_preferences[notification_type]
            if isinstance(type_settings, dict):
                return type_settings.get(channel, True)
        
        return True
    
    def is_quiet_hours(self):
        """Проверка находимся ли в режиме тишины."""
        if not self.quiet_hours_enabled or not self.quiet_hours_start or not self.quiet_hours_end:
            return False
        
        now = timezone.localtime().time()
        
        if self.quiet_hours_start < self.quiet_hours_end:
            # Обычный диапазон (например, 22:00 - 08:00 следующего дня не работает так)
            return self.quiet_hours_start <= now <= self.quiet_hours_end
        else:
            # Диапазон через полночь (например, 22:00 - 08:00)
            return now >= self.quiet_hours_start or now <= self.quiet_hours_end


class NotificationTemplate(models.Model):
    """
    Шаблон уведомления.
    Хранит шаблоны для разных типов уведомлений.
    """
    
    notification_type = models.CharField(
        max_length=50,
        unique=True,
        verbose_name='Тип уведомления'
    )
    
    # Шаблоны для разных каналов
    in_app_title = models.CharField(
        max_length=200,
        blank=True,
        verbose_name='Заголовок (внутри приложения)'
    )
    
    in_app_message = models.TextField(
        blank=True,
        verbose_name='Сообщение (внутри приложения)'
    )
    
    email_subject = models.CharField(
        max_length=200,
        blank=True,
        verbose_name='Тема email'
    )
    
    email_body = models.TextField(
        blank=True,
        verbose_name='Тело email (HTML)'
    )
    
    telegram_message = models.TextField(
        blank=True,
        verbose_name='Сообщение Telegram'
    )
    
    # Переменные шаблона
    variables = models.JSONField(
        default=list,
        blank=True,
        verbose_name='Переменные шаблона',
        help_text='Список доступных переменных для подстановки'
    )
    
    # Настройки
    is_active = models.BooleanField(
        default=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 = 'notification_templates'
        verbose_name = 'Шаблон уведомления'
        verbose_name_plural = 'Шаблоны уведомлений'
    
    def __str__(self):
        return f"Шаблон: {self.notification_type}"


class ParentChildNotificationSettings(models.Model):
    """
    Настройки уведомлений родителя для конкретного ребенка.
    Позволяет родителю настроить, какие уведомления получать для каждого ребенка отдельно.
    """
    
    parent = models.ForeignKey(
        'users.Parent',
        on_delete=models.CASCADE,
        related_name='child_notification_settings',
        verbose_name='Родитель'
    )
    
    child = models.ForeignKey(
        'users.Client',
        on_delete=models.CASCADE,
        related_name='parent_notification_settings',
        verbose_name='Ребенок'
    )
    
    # Общие настройки
    enabled = models.BooleanField(
        default=True,
        verbose_name='Уведомления включены'
    )
    
    # Настройки по типам уведомлений (JSON)
    # Формат: {"lesson_created": True, "homework_assigned": False, ...}
    type_settings = models.JSONField(
        default=dict,
        blank=True,
        verbose_name='Настройки по типам',
        help_text='Настройки для каждого типа уведомлений (True/False)'
    )
    
    # Временные метки
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name='Дата создания'
    )
    
    updated_at = models.DateTimeField(
        auto_now=True,
        verbose_name='Дата обновления'
    )
    
    class Meta:
        db_table = 'parent_child_notification_settings'
        verbose_name = 'Настройки уведомлений родителя для ребенка'
        verbose_name_plural = 'Настройки уведомлений родителей для детей'
        unique_together = [['parent', 'child']]
        indexes = [
            models.Index(fields=['parent', 'child']),
        ]
    
    def __str__(self):
        return f"Настройки уведомлений: {self.parent.user.get_full_name()} -> {self.child.user.get_full_name()}"
    
    def is_type_enabled(self, notification_type):
        """Проверка включен ли тип уведомления для этого ребенка."""
        if not self.enabled:
            return False
        
        # Если настройка для типа не указана, по умолчанию включено
        if notification_type in self.type_settings:
            return self.type_settings[notification_type]
        
        return True
    
    def set_type_enabled(self, notification_type, enabled):
        """Установить настройку для типа уведомления."""
        if not isinstance(self.type_settings, dict):
            self.type_settings = {}
        self.type_settings[notification_type] = enabled
        self.save(update_fields=['type_settings', 'updated_at'])
    
    def render(self, channel, context):
        """
        Рендерить шаблон с контекстом.
        
        Args:
            channel: Канал (in_app, email, telegram)
            context: Словарь с переменными для подстановки
        
        Returns:
            dict: Словарь с отрендеренным контентом
        """
        if channel == 'in_app':
            title = self._render_template(self.in_app_title, context)
            message = self._render_template(self.in_app_message, context)
            return {'title': title, 'message': message}
        
        elif channel == 'email':
            subject = self._render_template(self.email_subject, context)
            body = self._render_template(self.email_body, context)
            return {'subject': subject, 'body': body}
        
        elif channel == 'telegram':
            message = self._render_template(self.telegram_message, context)
            return {'message': message}
        
        return {}
    
    def _render_template(self, template, context):
        """Простая замена переменных в шаблоне."""
        if not template:
            return ''
        
        result = template
        for key, value in context.items():
            placeholder = '{' + key + '}'
            result = result.replace(placeholder, str(value))
        
        return result
