from model_utils import FieldTracker
from model_utils.models import TimeStampedModel, UUIDModel
from simple_history.models import HistoricalRecords

from django.contrib.auth import get_user_model
from django.contrib.postgres.fields import JSONField
from django.db import models
from django.utils.translation import gettext_lazy as _

from lms.core.models.mixins import ActiveFilterMixin
from lms.courses.models import Course

User = get_user_model()


class IntendedForChoice(models.TextChoices):
    ALL = 'all', _("Все пользователи")
    FOLLOWERS_ONLY = 'followers', _("Только подписчики")
    STUDENTS_ONLY = 'students', _("Только студенты")


class MailingQuerySet(ActiveFilterMixin, models.QuerySet):
    pass


class Mailing(TimeStampedModel):
    mailing_task = models.CharField(_("задача по рассылке"), max_length=255)
    name = models.CharField(_("название"), max_length=255)
    intended_for = models.CharField(
        _("получатели"),
        max_length=20,
        choices=IntendedForChoice.choices,
        default=IntendedForChoice.ALL,
    )
    is_active = models.BooleanField(_("активна"), default=True)

    objects = MailingQuerySet.as_manager()

    class Meta:
        ordering = ('-created',)
        verbose_name = _("рассылка")
        verbose_name_plural = _("рассылки")

    def __str__(self):
        return self.name


class CourseMailingQuerySet(ActiveFilterMixin, models.QuerySet):
    pass


class CourseMailing(TimeStampedModel):
    course = models.ForeignKey(
        Course,
        verbose_name=_("курс"),
        related_name='mailings',
        on_delete=models.CASCADE,
    )
    mailing = models.ForeignKey(
        Mailing,
        verbose_name=_("рассылка"),
        related_name='courses',
        on_delete=models.PROTECT,
    )
    is_active = models.BooleanField(_("активна"), default=True)
    can_group_with_others = models.BooleanField(
        _("группировать с другими курсами"),
        default=True,
        help_text=_("Разрешить группировать данную рассылку с другими курсами в одном письме."),
    )

    objects = CourseMailingQuerySet.as_manager()

    class Meta:
        ordering = ('-created',)
        verbose_name = _("рассылка по курсу")
        verbose_name_plural = _("рассылки по курсам")
        unique_together = (
            ('course', 'mailing'),
        )

    def __str__(self):
        return f'{self.course_id} | {self.mailing_id}'


class CourseFollowerQuerySet(ActiveFilterMixin, models.QuerySet):
    pass


class CourseFollower(TimeStampedModel):
    course = models.ForeignKey(
        Course,
        verbose_name=_("курс"),
        related_name='followers',
        on_delete=models.PROTECT,
    )
    user = models.ForeignKey(
        User,
        verbose_name=_("пользователь"),
        related_name='course_follows',
        on_delete=models.CASCADE,
    )
    is_active = models.BooleanField(_("активен"), default=True)
    subscribed_date = models.DateTimeField(_("дата подписки"), null=True, blank=True)
    unsubscribed_date = models.DateTimeField(_("дата отписки"), null=True, blank=True)

    class UnsubscriptionReasonChoice(models.TextChoices):
        USER = 'user', _("по инициативе пользователя")
        ENROLLED = 'enrolled', _("записался на курс")
        DISMISSED = 'dismissed', _("уволен")

    unsubscription_reason = models.CharField(
        max_length=10,
        verbose_name=_("причина отписки"),
        choices=UnsubscriptionReasonChoice.choices,
        null=True,
        blank=True,
    )

    objects = CourseFollowerQuerySet.as_manager()

    tracker = FieldTracker(fields=['is_active'])

    history = HistoricalRecords()

    class Meta:
        ordering = ('-created',)
        verbose_name = _("подписчик курса")
        verbose_name_plural = _("подписчики курсов")


class CourseFollowerHistory(CourseFollower.history.model):
    class Meta:
        proxy = True
        verbose_name = _("история подписчиков курсов")
        verbose_name_plural = _("истории подписчиков курсов")


class MailingEvent(TimeStampedModel, UUIDModel):
    class Status(models.TextChoices):
        PENDING = 'pending', _("Ожидает")
        PROCESSING = 'processing', _("В обработке")
        COMPLETED = 'completed', _("Завершено")
        CANCELLED = 'cancelled', _("Отменено")
        ERROR = 'error', _("Ошибка")

    mailing = models.ForeignKey(
        Mailing,
        verbose_name=_("рассылка"),
        related_name='events',
        on_delete=models.PROTECT,
    )
    # чтобы знать какие курсы попали в рассылку
    courses = models.ManyToManyField(
        Course,
        verbose_name=_("курсы"),
        related_name='mailing_events',
        blank=True,
    )
    recipients = models.ManyToManyField(
        User,
        verbose_name=_("получатели"),
        related_name='mailing_events',
        blank=True,
    )
    parameters = JSONField(_("параметры"), null=True, blank=True)
    status = models.CharField(_("статус"), max_length=20, choices=Status.choices, default=Status.PENDING)
    result_message = models.TextField(_("результат отправки"), blank=True)
    error_message = models.TextField(_("ошибки"), blank=True)

    scheduled = models.DateTimeField(_("запланировано"), null=True, blank=True)
    completed = models.DateTimeField(_("завершено"), null=True, blank=True)

    class Meta:
        ordering = ('-created',)
        verbose_name = _("событие в рассылке")
        verbose_name_plural = _("события в рассылках")

    def __str__(self):
        return str(self.pk)

    @property
    def course(self):
        num_courses = self.courses.count()
        if num_courses == 0:
            return _("<нет курсов>")
        elif num_courses == 1:
            return self.courses.first()

        return _("<несколько курсов>")

    @property
    def recipient(self):
        num_recipients = self.recipients.count()
        if num_recipients == 0:
            return _("<нет получателей>")
        elif num_recipients == 1:
            return self.recipients.first()

        return _("<несколько получателей>")
