"""
Custom middleware
"""

from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation
from django.shortcuts import redirect
from django.utils.dateparse import parse_datetime

from sga.backend.constants import STUDIO_USER_USERNAME, Roles
from sga.models import Course, Assignment, Student, Grader, Submission
from sga.backend.authentication import get_role


class SGAMiddleware(object):
    """
    Middleware for processing incoming LTI requests
    """
    ADMIN_ROLES = ["Administrator", "Instructor"]

    def process_request(self, request):  # pylint: disable=no-self-use
        """
        Processes incoming LTI requests
        """
        if not hasattr(request, "LTI"):
            raise ImproperlyConfigured("LTI middleware not installed")
        if "course_roles" not in request.session:
            request.session["course_roles"] = {}

        if request.lti_initial_request:
            if not request.lti_authentication_successful:
                # Raise 400; user is using bad LTI credentials
                raise SuspiciousOperation("Bad LTI credentials")
            if not request.LTI.get("context_id"):
                # Raise a 400 error
                raise SuspiciousOperation("No context_id in LTI parameters")
            if not request.LTI.get("resource_link_id"):
                # Raise a 400 error
                raise SuspiciousOperation("No resource_link_id in LTI parameters")
            if not request.LTI.get("lis_outcome_service_url"):
                return redirect("not_graded_block_error_page")
            if request.user.username == STUDIO_USER_USERNAME:
                return redirect("studio_message_page")
            # On the initial request, we have potentially gotten new information
            # from edX; update the database accordingly
            # Course
            course, _ = Course.objects.get_or_create(edx_id=request.LTI["context_id"])
            # Assignment
            due_date = request.POST.get("custom_component_due_date")
            if due_date:
                due_date = parse_datetime(due_date)
            name = request.POST.get("custom_component_display_name", request.LTI["resource_link_id"])
            defaults = {"course": course, "due_date": due_date, "name": name}
            assignment, _ = Assignment.objects.update_or_create(
                edx_id=request.LTI["resource_link_id"],
                defaults=defaults
            )
            if any([r for r in self.ADMIN_ROLES if r in request.LTI.get("roles", [])]):
                course.administrators.add(request.user)
                Grader.objects.filter(user=request.user, course=course).delete()
                Student.objects.filter(user=request.user, course=course).delete()
            else:
                course.administrators.remove(request.user)
                # Ensure the student object exists; graders also should have a student object, since
                # they are promoted from students and if they are ever demoted, their student data
                # should still exist
                Student.objects.get_or_create(course=course, user=request.user)
                # If this user is a student, we need to generate a Submission object and store
                # grade submission information
                submission, _ = Submission.objects.get_or_create(student=request.user, assignment=assignment)
                submission.edx_url = request.LTI["lis_outcome_service_url"]
                submission.result_id = request.POST.get("lis_result_sourcedid")
                submission.consumer_key = request.POST.get("oauth_consumer_key")
                submission.save()

            # We only check for role on the initial LTI request since the user's session in our tool
            # is expected to be short-lived enough to not warrant checking on every request.
            # We also need to cast str on course.id because the url parameters are passed as string
            # to the decorator and views.
            user_role = get_role(request.user, course.id)
            request.session["course_roles"][str(course.id)] = user_role
            # Redirect edX launch to the appropriate page
            return self.redirect_edx_launch(user_role, course, assignment)

    @staticmethod
    def redirect_edx_launch(user_role, course, assignment):
        """
        Redirects edX launch to the appropriate page
        """
        if user_role == Roles.student:
            return redirect("view_submission_as_student", course_id=course.id, assignment_id=assignment.id)
        if user_role in [Roles.admin, Roles.grader]:
            return redirect("view_assignment", course_id=course.id, assignment_id=assignment.id)
        raise Exception("Bad role %s" % user_role)

@@ -93,24 +93,71 @@
 usOperation%0A
+from django.http import HttpResponseBadRequest%0A
 from django.
@@ -1092,37 +1092,52 @@
    r
-aise SuspiciousOperation(%22Bad
+eturn HttpResponseBadRequest(%22Bad or missing
  LTI

Return "Bad or missing LTI credentials" message