from django.db.models import Count
from rest_framework.permissions import IsAuthenticated

from intranet.femida.src.actionlog.decorators import action_logged
from intranet.femida.src.api.core.views import (
    BaseView,
    BaseFormViewMixin,
    WorkflowView,
    QueryParamsFormView,
)
from intranet.femida.src.api.comments.views import CommentListCreateBaseView
from intranet.femida.src.api.problems.permissions import ProblemPermission
from intranet.femida.src.problems.complaints.controllers import create_complaint
from intranet.femida.src.problems.complaints.workflow import ComplaintWorkflow
from intranet.femida.src.problems.models import Complaint, Category
from intranet.femida.src.problems.helpers import get_active_complaints_counts, get_problems_stats

from . import forms
from . import serializers


class ComplaintListCreateView(BaseFormViewMixin, BaseView):

    # Note: здесь умышленно нет сериализатора detail_serializer_class.
    # Всё, что нужно фронту - это ответ 200. На списке задач фронт
    # просто увеличивает каунтер жалоб на 1, никак не используя
    # данные с бэка. На странице одной задачи после жалобы
    # фронт дергает ручку списка жалоб для получения обновленного списка.
    model_class = Complaint
    list_item_serializer_class = serializers.ComplaintSerializer
    validator_class = forms.ComplaintForm
    permission_classes = [
        IsAuthenticated,
        ProblemPermission,
    ]

    def get(self, *args, **kwargs):
        """
        Список жалоб на задачи
        """
        return self.list(*args, **kwargs)

    @action_logged('complaint_create')
    def post(self, *args, **kwargs):
        """
        Создание жалобы на задачу
        """
        return self.create(*args, **kwargs)

    def get_list_item_serializer_context(self):
        problem_ids = set()
        for complaint in self.page:
            problem_ids.add(complaint.problem_id)
            if complaint.original_problem_id:
                problem_ids.add(complaint.original_problem_id)
        problem_ids = list(problem_ids)
        return {
            'favorite_problem_ids': set(
                self.request.user.favorite_problems.values_list('id', flat=True)
            ),
            'active_complaints_counts': get_active_complaints_counts(problem_ids),
            'problems_stats': get_problems_stats(problem_ids),
        }

    def get_queryset(self):
        return (
            self.model_class.objects
            .annotate(comments_count=Count('comments'))
        )

    def filter_queryset(self, queryset):
        filter_form = forms.ComplaintListFilterForm(
            data=self.request.query_params,
        )
        self.validate(filter_form)

        filter_params = filter_form.cleaned_data
        if filter_params['only_active']:
            queryset = queryset.filter(is_active=True)

        if filter_params.get('moderator'):
            categories = Category.objects.filter(
                subscriptions__user=filter_params['moderator'],
            )
            queryset = queryset.filter(problem__categories__in=categories)

        if filter_params['category']:
            queryset = queryset.filter(problem__categories=filter_params['category'])

        if filter_params['problem']:
            queryset = queryset.filter(problem=filter_params['problem'])

        if filter_params['original_problem']:
            queryset = queryset.filter(original_problem=filter_params['original_problem'])

        if filter_params['resolution']:
            queryset = queryset.filter(resolution=filter_params['resolution'])

        return (
            queryset
            .order_by('-is_active')
            .distinct()
        )

    def perform_create(self, data):
        return create_complaint(data, initiator=self.request.user)


class ComplaintListFilterFormView(QueryParamsFormView):

    model_class = Complaint
    validator_class = forms.ComplaintListFilterFrontendForm
    form_serializer_class = serializers.ComplaintListFilterFormSerializer
    permission_classes = [
        IsAuthenticated,
        ProblemPermission,
    ]


class ComplaintWorkflowView(WorkflowView):

    model_class = Complaint
    workflow_class = ComplaintWorkflow
    permission_classes = [
        IsAuthenticated,
        ProblemPermission,
    ]

    def get_additional_response_data(self):
        return {
            'related_complaints': (
                serializers.ComplaintLiteSerializer(
                    self.action.extra_data['related_complaints'],
                    many=True,
                ).data
            )
        }

    @property
    def actionlog_name(self):
        return 'complaint_%s' % self.action_name


class ComplaintRejectView(ComplaintWorkflowView):

    action_name = 'reject'


class ComplaintResolveView(ComplaintWorkflowView):

    action_name = 'resolve'


class ComplaintCommentListCreateView(CommentListCreateBaseView):

    related_model_class = Complaint
    related_workflow_class = ComplaintWorkflow
    action_name = 'comment_add'
    actionlog_name = 'complaint_comment_add'
