from typing import Tuple

from django.conf import settings
from django.db.models import Count, Q
from django.db.models.query import ValuesQuerySet, QuerySet

from staff.femida.constants import VACANCY_STATUS

from staff.departments.models import Department, Vacancy
from staff.departments.vacancy_permissions import VacancyPermissions


class VacanciesFilterContext(object):
    VALID_STATUSES = [
        VACANCY_STATUS.ON_APPROVAL,
        VACANCY_STATUS.OFFER_ACCEPTED,
        VACANCY_STATUS.IN_PROGRESS,
        VACANCY_STATUS.OFFER_PROCESSING,
        VACANCY_STATUS.SUSPENDED,
    ]
    vacancy_fields = (
        'id',
        'name',
        'ticket',
        'offer_id',
        'headcount_position_code',
        'preprofile',
        'candidate_id',
        'candidate_first_name',
        'candidate_last_name',
        'candidate_login',
        'is_active',
        'status',
        'application_id',
        'department_id',
        'is_published'
    )

    dep_fields = (
        'id',
        'parent_id',
        'url',
        'tree_id',
        'lft',
        'rght',
        'name',
        'name_en',
        'level',
        'description',
        'description_en',
        'wiki_page',
        'maillists',
        'clubs',
    )

    filter_id = None

    def __init__(self, permissions: VacancyPermissions, **kwargs):
        self._permissions = permissions
        self.filter_q = Q(status__in=self.VALID_STATUSES)
        self.filter_q &= Q(**kwargs)

    def departments_qs(self, fields: Tuple = None) -> ValuesQuerySet:
        if fields is None:
            fields = self.dep_fields

        return (
            Department.objects
            .annotate(Count('femida_vacancies'))
            .filter(intranet_status=1)
            .exclude(id=settings.INTRANET_DISMISSED_STAFF_DEPARTMENT_ID)
            .values(*fields)
        )

    def vacancies_objects_qs(self) -> QuerySet:
        return (
            Vacancy.objects
            .filter(self._permissions.vacancy_filter_qs())
            .filter(self.filter_q)
            .exclude(department_id=None)
            .exclude(department_id=settings.INTRANET_DISMISSED_STAFF_DEPARTMENT_ID)
        )

    def vacancies_qs(self, fields: Tuple = None) -> ValuesQuerySet:
        fields = fields or self.vacancy_fields
        return self.vacancies_objects_qs().values(*fields)
