import waffle

from django.core.exceptions import PermissionDenied
from django.shortcuts import _get_queryset
from django.http import Http404
from django.db.models import sql
from django.db.models.base import ModelBase

from intranet.femida.src.permissions.helpers import get_manager
from intranet.femida.src.permissions.managers.base import PermQuery


def _get_safe_queryset(klass):
    """
    Если был передан класс модели, то мы хотим использовать не дефолтный менеджер, а безопасный.
    """
    if isinstance(klass, ModelBase):
        return get_manager(klass, unsafe=False).all()
    return _get_queryset(klass)


def get_object_or_40x(klass, *args, **kwargs):
    """
    Замена get_object_or_404 из django
    Поскольку у нас права на уровне менеджера модели, нам нужно возвращать либо 404, либо 403.
    :param klass: Model или QuerySet
    """
    queryset = _get_safe_queryset(klass)

    try:
        return queryset.get(*args, **kwargs)
    except queryset.model.DoesNotExist:
        error_msg = 'No %s matches the given query.' % queryset.model._meta.object_name

        if isinstance(queryset.query, PermQuery) and not waffle.switch_is_active('is_rkn'):
            # Копируем queryset и подменяем его query, подсовывая в clone базовый Query,
            # тем самым получая тот же самый query, но без фильтрации из PermQuery
            copied_queryset = queryset.all()
            copied_queryset.query = copied_queryset.query.chain(sql.Query)
            try:
                copied_queryset.get(*args, **kwargs)
            except queryset.model.DoesNotExist:
                raise Http404(error_msg)
            else:
                raise PermissionDenied
        else:
            raise Http404(error_msg)
