import logging

from django.conf import settings
from django.db import models
from model_utils.models import TimeStampedModel

from intranet.femida.src.applications.models import Application
from intranet.femida.src.attachments.models import Attachment
from intranet.femida.src.communications import choices
from intranet.femida.src.communications.managers import MessageManager
from intranet.femida.src.permissions.managers.candidate import CandidatePermManager
from intranet.femida.src.permissions.managers.message import MessagePermManager
from intranet.femida.src.wf.models import WFModelMixin


logger = logging.getLogger(__name__)


class Message(WFModelMixin, TimeStampedModel):

    unsafe = MessageManager()
    objects = MessagePermManager()

    WIKI_FIELDS_MAP = {
        'text': 'html',
    }

    candidate = models.ForeignKey(
        to='candidates.Candidate',
        related_name='messages',
        on_delete=models.PROTECT,
        db_constraint=False,
    )
    application = models.ForeignKey(
        to='interviews.Application',
        related_name='messages',
        on_delete=models.PROTECT,
        db_constraint=False,
        null=True,
        blank=True,
    )
    type = models.CharField(
        max_length=32,
        choices=choices.MESSAGE_TYPES,
        default=choices.MESSAGE_TYPES.internal,
        db_index=True,
    )
    status = models.CharField(
        max_length=16,
        choices=choices.MESSAGE_STATUSES,
        default=choices.MESSAGE_STATUSES.sent,
        db_index=True,
    )
    error = models.TextField(
        blank=True,
        null=True,
        help_text='Подробности ошибки, если письмо не удалось отправить',
    )
    is_changed = models.NullBooleanField()
    schedule_time = models.DateTimeField(blank=True, null=True)
    subject = models.CharField(max_length=255, blank=True)

    # В случае внутренней/исходящей коммуникации - это вики-разметка
    # В случае входящей - сырой body письма внутри тега <# #> - тоже валидная wiki-разметка
    text = models.TextField()
    # Отформатированная вики-форматтером wiki-разметка
    html = models.TextField(blank=True)
    # Вычищенный текст из Сепаратора
    cleaned_text = models.TextField(blank=True, null=True)
    # Входящую коммуникацию из Сепаратора, созданную
    # до тикета https://st.yandex-team.ru/FEMIDA-2514 форматировать нельзя
    ignore_wiki_format = models.NullBooleanField()

    email = models.CharField(max_length=255, default='', blank=True, db_index=True)
    author = models.ForeignKey(
        to=settings.AUTH_USER_MODEL,
        related_name='messages',
        on_delete=models.PROTECT,
        null=True,
        blank=True,
    )
    # Message-Id gotten from seporator for incomming messages or constructed by us for outcoming
    separator_message_id = models.CharField(max_length=255, blank=True)

    attachments = models.ManyToManyField(
        to='attachments.Attachment',
        through='communications.MessageAttachment',
        related_name='messages',
    )

    @property
    def vacancy_name(self):
        try:
            return self.application.vacancy.composite_name
        except Application.DoesNotExist:
            return ''

    def format_wiki_fields(self, *args, **kwargs):
        if self.ignore_wiki_format:
            logger.error('Can not format message instance %d: ignore_wiki_format is True', self.id)
            return False
        return super().format_wiki_fields(*args, **kwargs)

    def save(self, *args, **kwargs):
        if self.ignore_wiki_format:
            kwargs['ignore_wiki_format'] = True
            kwargs['force_wiki_format'] = False
        super().save(*args, **kwargs)

    def __str__(self):
        return 'Message {}: {}'.format(self.id, self.subject)

    class Meta:
        default_manager_name = 'unsafe'
        indexes = [
            models.Index(
                fields=['id', 'modified'],
                name='message_id_modified_idx',
            ),
        ]


class MessageAttachment(TimeStampedModel):

    unsafe = models.Manager()
    objects = CandidatePermManager(perm_prefix='message__candidate')

    message = models.ForeignKey(
        to=Message,
        related_name='message_attachments',
        on_delete=models.PROTECT,
    )
    content_type = models.CharField(max_length=255, blank=True)
    attachment = models.ForeignKey(
        to=Attachment,
        on_delete=models.PROTECT,
        related_name='message_attachments',
    )

    def __str__(self):
        return self.attachment.name

    class Meta:
        default_manager_name = 'unsafe'


# TODO: Вынести из communications
class MessageTemplate(TimeStampedModel):

    # Теперь модель используется не только для шаблонов в коммуникациях.
    type = models.CharField(
        max_length=32,
        choices=choices.MESSAGE_TEMPLATE_TYPES,
        default=choices.MESSAGE_TEMPLATE_TYPES.communication,
    )

    # На случай, если захочется вынести категории в отдельную таблицу,
    # не будем использовать слово category
    category_name = models.CharField(max_length=255, blank=True)
    name = models.CharField(max_length=255)
    subject = models.CharField(max_length=255, blank=True)
    text = models.TextField()
    is_active = models.BooleanField(default=True)

    def __str__(self):
        return '{}, {}'.format(self.category_name, self.name)


class Reminder(TimeStampedModel):

    user = models.ForeignKey(
        to=settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name='reminders',
    )
    message = models.ForeignKey(
        to=Message,
        on_delete=models.SET_NULL,
        related_name='reminders',
        null=True,
    )
    remind_at = models.DateTimeField()
    status = models.CharField(
        max_length=32,
        choices=choices.REMINDER_STATUSES,
        default=choices.REMINDER_STATUSES.scheduled,
    )

    def __str__(self):
        return 'Reminder {}'.format(self.id)
