"""
Модели, использующиеся в приложении.
"""
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils import timezone

from access_controller.settings import ZENDESK_ROLES


class UserProfile(models.Model):
    """
    Модель профиля пользователя.
    Профиль создается и изменяется при создании и изменении модель User.
    """

    class Meta:
        permissions = (
            ('has_control_access', 'Can view admin page'),
        )

    user = models.OneToOneField(to=get_user_model(), on_delete=models.CASCADE, help_text='Пользователь')
    role = models.CharField(default='None', max_length=100, help_text='Глобальное имя роли пользователя')
    custom_role_id = models.BigIntegerField(default=0, help_text='Код роли пользователя')
    image = models.URLField(null=True, blank=True, help_text='Аватарка')
    name = models.CharField(default='None', max_length=100, help_text='Имя пользователя на нашем сайте')

    @property
    def zendesk_role(self) -> str:
        """
        Роль пользователя в Zendesk, либо UNDEFINED, если пользователь не найден.
        """
        for role, r_id in ZENDESK_ROLES.items():
            if r_id == self.custom_role_id:
                return role
        return 'UNDEFINED'


@receiver(post_save, sender=get_user_model())
def create_user_profile(instance: get_user_model(), created: bool, **kwargs) -> None:
    """
    Функция создания профиля пользователя (Userprofile) при регистрации пользователя.

    :param instance: Экземпляр класса User
    :param created: Существует ли пользователь
    :param kwargs: Параметры
    :return: Обновленный список объектов профилей пользователей
    """
    if created:
        UserProfile.objects.create(user=instance)


@receiver(post_save, sender=get_user_model())
def save_user_profile(instance: get_user_model(), **kwargs) -> None:
    """
    Функция записи БД профиля пользователя.

    :param instance: Экземпляр класса User
    :param kwargs: Параметры
    :return: Запись профиля пользователя
    """
    instance.userprofile.save()


class RoleChangeLogs(models.Model):
    """
    Модель для логгирования изменений ролей пользователя
    """
    user = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE,
                             help_text='Пользователь, которому присвоили другую роль')
    old_role = models.BigIntegerField(default=0, help_text='Старая роль')
    new_role = models.BigIntegerField(default=0, help_text='Присвоенная роль')
    change_time = models.DateTimeField(default=timezone.now, help_text='Дата и время изменения роли')
    changed_by = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name='changed_by',
                                   help_text='Кем была изменена роль')


class UnassignedTicketStatus(models.IntegerChoices):
    """
    Модель статусов не распределенных тикетов.

    :param UNASSIGNED: Снят с пользователя, перенесён в буферную группу
    :param RESTORED: Авторство восстановлено
    :param NOT_FOUND: Пока нас не было, тикет испарился из буферной группы.
                      Дополнительные действия не требуются
    :param CLOSED: Тикет уже был закрыт. Дополнительные действия не требуются
    :param SOLVED: Тикет решён. Записан на пользователя с почтой SOLVED_TICKETS_EMAIL
    """
    UNASSIGNED = 0, 'Снят с пользователя, перенесён в буферную группу'
    RESTORED = 1, 'Авторство восстановлено'
    NOT_FOUND = 2, 'Пока нас не было, тикет был перенесен из ' \
                   'буферной группы. Дополнительные действия не требуются'
    CLOSED = 3, 'Тикет уже был закрыт. Дополнительные действия не требуются'
    SOLVED = 4, 'Тикет решён. Записан на пользователя с почтой SOLVED_TICKETS_EMAIL'


class UnassignedTicket(models.Model):
    """
    Модель не распределенного тикета.
    """
    assignee = models.ForeignKey(to=get_user_model(), on_delete=models.CASCADE, related_name='tickets',
                                 help_text='Пользователь, с которого снят тикет')
    ticket_id = models.IntegerField(help_text='Номер тикета, для которого сняли ответственного')
    status = models.IntegerField(choices=UnassignedTicketStatus.choices, default=UnassignedTicketStatus.UNASSIGNED,
                                 help_text='Статус тикета')
