from collections import defaultdict

from django.conf import settings
from django.db.models import Count, CharField

from intranet.femida.src.core.db import MapperExpression
from intranet.femida.src.core.db.helpers import get_count_subquery
from intranet.femida.src.interviews.models import Assignment
from intranet.femida.src.problems.models import Complaint, Problem


def add_active_complaints_count(qs):
    return qs.annotate(
        active_complaints_count=get_count_subquery(
            queryset=Complaint.objects.filter(is_active=True),
            reverse_related_name='problem_id',
        )
    )


def get_active_complaints_counts(problem_ids=None):
    """
    :param problem_ids: Список id задачи или queryset или None. Если None, то все задачи
    :return: Словарь, где ключ - задача, значение - количество активных жалоб
    """
    qs = Problem.objects.all()
    if problem_ids is not None:
        qs = qs.filter(id__in=problem_ids)
    return dict(add_active_complaints_count(qs).values_list('id', 'active_complaints_count'))


def get_problems_stats(problem_ids):
    """
    :param problem_ids: Список id задачи
    :return: defaultdict, где ключ - id задачи, значение - статистика решения
    """
    grades_map = {
        1: 'bad',
        3: 'norm',
        5: 'excellent',
    }

    assignments_data = (
        Assignment.objects
        .values('problem_id', 'grade')
        .annotate(count=Count('id'))
        .filter(
            problem__in=problem_ids,
            grade__in=grades_map.keys(),
        )
        .order_by()
        .values_list(
            'problem_id',
            MapperExpression('grade', mapping=grades_map, output_field=CharField()),
            'count',
        )
    )

    result = defaultdict(lambda: {
        'bad': 0,
        'norm': 0,
        'excellent': 0,
        'total': 0,
    })

    for problem_id, grade, count in assignments_data:
        result[problem_id][grade] = count
        result[problem_id]['total'] += count

    return result


def has_access_to_problems(user):
    """
    Доступ к задачам есть только у рекрутеров
    и у сотрудников из ветки Яндекс, которые не являются стажёрами
    """
    return (
        user.is_recruiter
        or user.department.is_in_tree(settings.YANDEX_DEPARTMENT_ID)
        and not user.is_intern
    )
