from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.db.models import Q

from intranet.femida.src.notifications.base import (
    FetchingNotificationBase,
    PersonalizedNotificationBase,
    R,
)
from intranet.femida.src.notifications.utils import (
    get_problem_message_id,
    get_problem_email_subject,
)
from intranet.femida.src.wf.base import get_diff_in_json


User = get_user_model()


def _get_moderators(categories):
    perm = Permission.objects.get(codename='change_complaint')
    return set(
        User.objects
        .filter(
            Q(subscriptions__category__in=categories)
            & (
                Q(groups__permissions=perm)
                | Q(user_permissions=perm)
                | Q(is_superuser=True)
            )
        )
    )


moderators_rcv = R(lambda x: _get_moderators(x.instance.categories.all()))
initiator_rcv = R(lambda x: [x.initiator])


class ProblemNotification(FetchingNotificationBase):

    subject_prefix = None

    def get_subject(self):
        return get_problem_email_subject(self.instance, self.subject_prefix)

    def get_thread_id(self):
        return get_problem_message_id(self.instance)


class ProblemCreatedNotification(ProblemNotification):

    subject_prefix = 'Задача добавлена'
    template_name = 'email/problems/create.html'
    receivers = moderators_rcv - initiator_rcv
    is_thread_beginning = True


class ProblemUpdatedNotification(ProblemNotification):

    subject_prefix = 'Задача изменена'
    template_name = 'email/problems/update.html'

    def __init__(self, instance, initiator, old_instance, old_categories, **kwargs):
        super().__init__(
            instance=instance,
            initiator=initiator,
            old_instance=old_instance,
            old_categories=old_categories,
            **kwargs
        )
        self.old_instance = old_instance
        self.old_categories = set(old_categories)
        self.categories = set(self.instance.categories.all())

    def fetch_receivers(self):
        receivers = _get_moderators(self.old_categories | self.categories)
        receivers.add(self.instance.created_by)
        receivers.discard(self.initiator)
        return receivers

    def get_common_context(self):
        diff = {
            'summary': None,
            'description': None,
            'solution': None,
        }

        for key in diff:
            old_value = getattr(self.old_instance, key)
            new_value = getattr(self.instance, key)
            if old_value != new_value:
                diff[key] = get_diff_in_json(old_value, new_value)

        diff['categories'] = {
            'removed': self.old_categories - self.categories,
            'unchanged': self.old_categories & self.categories,
            'added': self.categories - self.old_categories,
        }

        context = super().get_common_context()
        context['old_instance'] = self.old_instance
        context['diff'] = diff
        return context


class ComplaintCreatedNotification(PersonalizedNotificationBase):

    subject_prefix = 'Жалоба на задачу'
    template_name = 'email/complaint-create.html'

    def get_subject(self, receiver):
        return get_problem_email_subject(self.instance.problem, self.subject_prefix)

    def get_thread_id(self):
        return get_problem_message_id(self.instance.problem)

    def get_context_personalization(self):
        result = {
            self.instance.problem.created_by: {
                'is_moderator': False,
            }
        }
        for moderator in _get_moderators(self.instance.problem.categories.all()):
            result[moderator] = {
                'is_moderator': True,
            }
        result.pop(self.initiator, None)
        return result
