from functools import wraps

from django.contrib import messages
from django.http import JsonResponse
from django.shortcuts import get_object_or_404, redirect
from django.urls import reverse

from reviews.models import Review


def is_ajax_request(request) -> bool:
    return request.headers.get("X-Requested-With") == "XMLHttpRequest"


def author_required(view):
    @wraps(view)
    def wrapped(request, review_id, *args, **kwargs):
        review = get_object_or_404(Review, pk=review_id)
        if not review.is_author(request.user):
            from django.http import Http404

            raise Http404()
        return view(request, review, *args, **kwargs)

    return wrapped


def main_author_required(view):
    @wraps(view)
    def wrapped(request, review_id, *args, **kwargs):
        review = get_object_or_404(Review, pk=review_id)
        if not review.is_main_author(request.user):
            from django.http import HttpResponseForbidden

            return HttpResponseForbidden()
        return view(request, review, *args, **kwargs)

    return wrapped


def phase_required(step_key: str):
    def decorator(view):
        @wraps(view)
        def wrapped(request, review, *args, **kwargs):
            from rsl.services.workflow import get_conducting_steps

            for step in get_conducting_steps(review):
                if step.key == step_key and step.blocked:
                    if is_ajax_request(request):
                        return JsonResponse(
                            {"ok": False, "error": step.block_reason}, status=403
                        )
                    messages.warning(request, step.block_reason)
                    if step_key == "import" and not review.sources.exists():
                        return redirect(
                            reverse("planning:protocol", kwargs={"review_id": review.id})
                            + "#bases"
                        )
                    return redirect(
                        reverse("reviews:detail", kwargs={"review_id": review.id}) + "#fluxo"
                    )
            return view(request, review, *args, **kwargs)

        return wrapped

    return decorator
