from django.contrib.auth import get_user_model

from intranet.femida.src.api.core.serializers import IdNameSerializer
from intranet.femida.src.attachments.models import Attachment
from intranet.femida.src.candidates.choices import CANDIDATE_STATUSES
from intranet.femida.src.candidates.models import Consideration
from intranet.femida.src.communications.choices import MESSAGE_TYPES
from intranet.femida.src.interviews.choices import APPLICATION_STATUSES
from intranet.femida.src.notifications.base import FetchingNotificationBase, R
from intranet.femida.src.notifications.headers import (
    get_candidate_headers,
    get_application_headers,
    get_vacancy_headers,
)
from intranet.femida.src.notifications.utils import (
    get_candidate_message_id,
    get_candidate_email_subject,
    get_application_email_subject,
)
from intranet.femida.src.vacancies.choices import VACANCY_ROLES
from intranet.femida.src.vacancies.models import VacancyMembership

from . import serializers


User = get_user_model()


def _get_hiring_teams_members(notification):
    application = notification.instance.application
    roles = [VACANCY_ROLES.main_recruiter, VACANCY_ROLES.recruiter]
    if application.status == APPLICATION_STATUSES.in_progress:
        roles.extend([
            VACANCY_ROLES.hiring_manager,
            VACANCY_ROLES.responsible,
        ])
    return set(
        VacancyMembership.unsafe
        .filter(
            vacancy=application.vacancy,
            role__in=roles,
        )
        .values_list('member__email', flat=True)
    )


def _get_candidate_actual_responsibles(notification):
    candidate = notification.candidate
    if candidate.status == CANDIDATE_STATUSES.in_progress:
        obj = candidate
    else:
        obj = (
            Consideration.unsafe
            .filter(
                candidate_id=candidate.id,
                state=Consideration.STATES.archived,
            )
            .order_by('-finished')
            .first()
        )
    need_mailing_list = (
        notification.instance.type == MESSAGE_TYPES.incoming
        and (
            obj is None
            or not obj.responsibles.exists()
        )
    )
    if need_mailing_list:
        return ['job-closed-appls@yandex-team.ru']
    return obj.responsibles.values_list('email', flat=True) if obj is not None else []


candidate_responsibles_rcv = R(lambda x: (
    x.instance.candidate.responsibles.values_list('email', flat=True)
))
candidate_last_consideration_responsibles_rcv = R(_get_candidate_actual_responsibles)
author_rcv = R(lambda x: [x.instance.author.email] if x.instance.author else [])
hiring_teams_members_rcv = R(_get_hiring_teams_members)
initiator_rcv = R(lambda x: [x.initiator])


class MessageCreatedNotificationBase(FetchingNotificationBase):

    subject_prefix = None

    @property
    def candidate(self):
        return self.instance.candidate

    def get_subject(self):
        return get_candidate_email_subject(self.candidate, self.subject_prefix)

    def get_thread_id(self):
        return get_candidate_message_id(self.candidate)

    def get_common_context(self):
        context = super().get_common_context()
        context['message'] = serializers.MessageSerializer(self.instance).data
        attachments = Attachment.objects.filter(
            message_attachments__message=self.instance,
        )
        context['attachments'] = IdNameSerializer(attachments, many=True).data
        context['candidate'] = serializers.CandidateSerializer(self.candidate).data
        return context

    def get_femida_headers(self):
        headers = super().get_femida_headers()
        headers.update(get_candidate_headers(self.instance.candidate_id))
        return headers


# TODO: переместить в applications и переименовать в рамках FEMIDA-3828
class InternalMessageCreatedNotification(MessageCreatedNotificationBase):

    subject_prefix = 'Комментарий добавлен'
    template_name = 'mail/applications/comment-add.html'
    receivers = candidate_responsibles_rcv + hiring_teams_members_rcv - author_rcv - initiator_rcv

    def get_subject(self):
        return get_application_email_subject(self.instance.application, self.subject_prefix)

    def get_common_context(self):
        context = super().get_common_context()
        context['application'] = serializers.ApplicationSerializer(self.instance.application).data
        context['vacancy'] = serializers.VacancySerializer(self.instance.application.vacancy).data
        return context

    def get_femida_headers(self):
        headers = super().get_femida_headers()
        headers.update(get_application_headers([self.instance.application_id]))
        headers.update(get_vacancy_headers([self.instance.application.vacancy_id]))
        return headers


class ExternalMessageCreatedNotification(MessageCreatedNotificationBase):

    template_name = 'email/message-create.html'
    receivers = candidate_last_consideration_responsibles_rcv - author_rcv

    def get_subject(self):
        if self.instance.type == MESSAGE_TYPES.incoming:
            self.subject_prefix = 'Письмо получено'
        else:
            self.subject_prefix = 'Письмо отправлено'
        return super().get_subject()


class ExternalMessageFailedNotification(MessageCreatedNotificationBase):

    subject_prefix = 'Не удалось отправить письмо'
    template_name = 'email/message-fail.html'
    receivers = author_rcv


class NoteCreatedNotification(MessageCreatedNotificationBase):

    subject_prefix = 'Заметка создана'
    template_name = 'email/message-create.html'
    receivers = candidate_last_consideration_responsibles_rcv - author_rcv
