import json
import waffle

from constance import config
from rest_framework import permissions, status

from intranet.femida.src.api.core.errors import format_non_form_message
from intranet.femida.src.api.core.views import ResponseError
from intranet.femida.src.candidates.deduplication.exceptions import HasDuplicatesError
from intranet.femida.src.candidates.helpers import get_active_duplication_case_ids
from intranet.femida.src.candidates.models import Candidate


class YTCandidateUploadPermission(permissions.BasePermission):
    """
    Право на обработку кандидатов из YT-таблицы
    """
    def has_permission(self, request, view):
        upload_sources = json.loads(config.YT_CANDIDATE_UPLOAD_SOURCES)
        return (
            upload_sources.get(request.user.username)
            and request.user.has_perm('permissions.can_use_yt_candidate_uploader')
        )


class YTCandidateScoringPermission(permissions.BasePermission):
    """
    Право на заливку скорингов из YT-таблицы
    """
    def has_permission(self, request, view):
        return request.user.has_perm('permissions.can_use_yt_candidate_scoring_uploader')


class NoDuplicatesPermission(permissions.BasePermission):
    """
    Право, разрешающее выполнение какого-либо действия над кандидатом,
    только при отсутствии активных дублей у этого кандидата.
    """
    def has_object_permission(self, request, view, obj):
        assert isinstance(obj, Candidate)
        if waffle.switch_is_active('enable_has_duplicates_error'):
            self._check_for_duplicates(obj)
        return True

    def _check_for_duplicates(self, candidate: Candidate):
        """
        Проверяет, нет ли у кандидата дублей.
        Если есть, не просто отдаёт False, а выкидывает исключение, чтобы сразу отдать ответ.
        Сделано так для того, чтобы добавить параметров в ошибку.
        """
        duplication_case_ids = get_active_duplication_case_ids(candidate.id)
        if duplication_case_ids:
            data = format_non_form_message(HasDuplicatesError(duplication_case_ids))
            raise ResponseError(data=data, status=status.HTTP_403_FORBIDDEN)
