from django.core.exceptions import PermissionDenied
from .models import Case, CaseCollection, Series


def user_is_author_or_atlas_series_checker_or_atlas_marker_or_open_access(function):
    """Decorator to check if user is author of the series, 
    an atlas editor, an atlas marker, or if the series is open access. 
    Used for series-level permissions. 
    
    Requires the decorated view to have a "pk" or "series_id" kwarg to identify the series.
    """
    def wrap(request, *args, **kwargs):
        if "pk" in kwargs:
            series = Series.objects.get(pk=kwargs["pk"])
        elif "series_id" in kwargs:
            series = Series.objects.get(pk=kwargs["series_id"])
        if (
            request.user in series.get_author_objects()
            or series.open_access
            or request.user.groups.filter(name="atlas_editor").exists()
            or request.user.groups.filter(name="atlas_marker").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)
        else:
            raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap


def user_is_author_or_atlas_series_checker(function):
    def wrap(request, *args, **kwargs):
        if "pk" in kwargs:
            series = Series.objects.get(pk=kwargs["pk"])
        elif "series_id" in kwargs:
            series = Series.objects.get(pk=kwargs["series_id"])
        if (
            request.user in series.get_author_objects()
            or request.user.groups.filter(name="atlas_editor").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)
        else:
            raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap


def user_has_case_view_access(function):
    def wrap(request, *args, **kwargs):
        if "pk" in kwargs:
            atlas = Case.objects.get(pk=kwargs["pk"])
        elif "case_id" in kwargs:
            atlas = Case.objects.get(pk=kwargs["case_id"])

        # If open access everyone can view
        if atlas.open_access:
            return function(request, *args, **kwargs)
        if (
            request.user in atlas.author.all()
            or request.user.groups.filter(name="atlas_editor").exists()
            or request.user.groups.filter(name="atlas_marker").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)
        else:
            raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap


def user_is_author_or_atlas_editor(function):
    def wrap(request, *args, **kwargs):
        if "pk" in kwargs:
            atlas = Case.objects.get(pk=kwargs["pk"])
        elif "case_id" in kwargs:
            atlas = Case.objects.get(pk=kwargs["case_id"])
        if (
            request.user in atlas.author.all()
            or request.user.groups.filter(name="atlas_editor").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)
        else:
            raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap

def user_is_collection_author_or_atlas_editor(function):
    def wrap(request, *args, **kwargs):
        if "exam_id" in kwargs:
            atlas = CaseCollection.objects.get(pk=kwargs["exam_id"])
        elif "collection_id" in kwargs:
            atlas = CaseCollection.objects.get(pk=kwargs["collection_id"])
        else:
            atlas = CaseCollection.objects.get(pk=kwargs["pk"])
        if (
            request.user in atlas.author.all()
            or request.user.groups.filter(name="atlas_editor").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)

        # Allow access if request.user is the supervisor of the target user and sharing is enabled
        user_pk = kwargs.get("user_pk") or kwargs.get("user_id")
        if user_pk:
            from django.contrib.auth import get_user_model
            from django.contrib.contenttypes.models import ContentType
            from generic.models import CidUserExam
            try:
                target_user = get_user_model().objects.get(pk=user_pk)
                sup = target_user.userprofile.supervisor
                if sup and sup.user_id == request.user.id:
                    ct = ContentType.objects.get_for_model(CaseCollection)
                    cid_user_exam = CidUserExam.objects.filter(
                        content_type=ct,
                        object_id=atlas.pk,
                        user_user=target_user
                    ).first()
                    if (cid_user_exam and cid_user_exam.share_with_supervisor) or atlas.results_supervisor_visible:
                        return function(request, *args, **kwargs)
            except Exception:
                pass

        raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap


def user_is_atlas_editor(function):
    def wrap(request, *args, **kwargs):
        if (
            request.user.groups.filter(name="atlas_editor").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)
        else:
            raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap


def user_is_atlas_marker(function):
    def wrap(request, *args, **kwargs):
        if (
            request.user.groups.filter(name="atlas_marker").exists()
            or request.user.is_superuser
        ):
            return function(request, *args, **kwargs)
        else:
            raise PermissionDenied

    wrap.__doc__ = function.__doc__
    wrap.__name__ = function.__name__
    return wrap
