import graphene
from django.core.exceptions import MultipleObjectsReturned
from graphene import relay
from graphql_relay import from_global_id
from rest_framework.exceptions import PermissionDenied

from api.utils import get_object
from assignments.models import Assignment, SubmissionFeedback
from assignments.schema.types import AssignmentNode, StudentSubmissionNode, SubmissionFeedbackNode
from .inputs import AssignmentInput, SubmissionFeedbackInput


class UpdateAssignment(relay.ClientIDMutation):
    class Input:
        assignment = graphene.Argument(AssignmentInput)

    updated_assignment = graphene.Field(AssignmentNode)
    submission = graphene.Field(StudentSubmissionNode)
    successful = graphene.Boolean()
    errors = graphene.List(graphene.String)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        assignment_data = kwargs.get('assignment')
        assignment = get_object(Assignment, assignment_data.get('id'))
        student = info.context.user

        # todo: replace with middleware
        if student.read_only:
            raise PermissionError('No valid license')

        try:
            (submission, _created) = assignment.submissions.get_or_create(student=student)
        except MultipleObjectsReturned:
            for submission in assignment.submissions.filter(student=student):
                submission.delete()
            submission = assignment.submissions.create(student=student)
        submission.text = assignment_data.get('answer', '')
        submission.document = assignment_data.get('document', '')
        final = assignment_data.get('final')
        if final is not None:
            submission.final = final
        submission.save()
        return cls(successful=True, updated_assignment=assignment, submission=submission, errors=None)


class UpdateSubmissionFeedback(relay.ClientIDMutation):
    class Input:
        submission_feedback = graphene.Argument(SubmissionFeedbackInput)

    updated_submission_feedback = graphene.Field(SubmissionFeedbackNode)
    successful = graphene.Boolean()
    errors = graphene.List(graphene.String)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        submission_feedback_data = kwargs.get('submission_feedback')
        user = info.context.user
        student_submission_id = from_global_id(submission_feedback_data['student_submission'])[1]

        if not user.has_perm('users.can_manage_school_class_content'):
            raise PermissionDenied('Missing permissions')

        # todo: replace with middleware
        if user.read_only:
            raise PermissionError('No valid license')

        (submission_feedback, created) = SubmissionFeedback.objects.get_or_create(teacher=user,
                                                                                  student_submission_id=student_submission_id)

        final = submission_feedback_data.get('final') if 'final' in submission_feedback_data else submission_feedback.final

        submission_feedback.final = final
        submission_feedback.text = submission_feedback_data.get('text')
        submission_feedback.save()

        return cls(successful=True, updated_submission_feedback=submission_feedback, errors=None)


class AssignmentMutations(object):
    update_assignment = UpdateAssignment.Field()
    update_submission_feedback = UpdateSubmissionFeedback.Field()
