from functools import wraps

from django.http.response import HttpResponse

from atlassian_jwt_auth.frameworks.django.decorators import with_asap


def validate_asap(issuers=None, subjects=None, required=True):
    """Decorator to allow endpoint-specific ASAP authorization, assuming ASAP
    authentication has already occurred.

    :param list issuers: A list of issuers that are allowed to use the
        endpoint.
    :param list subjects: A list of subjects that are allowed to use the
        endpoint.
    :param boolean required: Whether or not to require ASAP on this endpoint.
        Note that requirements will be still be verified if claims are present.
    """
    def validate_asap_decorator(func):
        @wraps(func)
        def validate_asap_wrapper(request, *args, **kwargs):
            asap_claims = getattr(request, 'asap_claims', None)
            if required and not asap_claims:
                message = 'Unauthorized: Invalid or missing token'
                response = HttpResponse(message, status=401)
                response['WWW-Authenticate'] = 'Bearer'
                return response

            if asap_claims:
                iss = asap_claims['iss']
                if issuers and iss not in issuers:
                    message = 'Forbidden: Invalid token issuer'
                    return HttpResponse(message, status=403)

                sub = asap_claims.get('sub')
                if subjects and sub not in subjects:
                    message = 'Forbidden: Invalid token subject'
                    return HttpResponse(message, status=403)

            return func(request, *args, **kwargs)

        return validate_asap_wrapper
    return validate_asap_decorator


def requires_asap(issuers=None, subject_should_match_issuer=None, func=None):
    """Decorator for Django endpoints to require ASAP

    :param list issuers: *required The 'iss' claims that this endpoint is from.
    """
    return with_asap(func=func,
                     required=True,
                     issuers=issuers,
                     subject_should_match_issuer=subject_should_match_issuer)