import graphene
import structlog
from graphene.types.generic import GenericScalar
from graphene_django.types import ErrorType

from vbv_lernwelt.course.models import CourseSession
from vbv_lernwelt.feedback.graphql.types import (
    FeedbackResponseObjectType as FeedbackResponseType,
)
from vbv_lernwelt.feedback.serializers import (
    CourseFeedbackSerializerUK,
    CourseFeedbackSerializerVV,
)
from vbv_lernwelt.feedback.services import update_feedback_response
from vbv_lernwelt.iam.permissions import has_course_session_access
from vbv_lernwelt.learnpath.models import (
    LearningContentFeedbackUK,
    LearningContentFeedbackVV,
)

logger = structlog.get_logger(__name__)


# https://medium.com/open-graphql/jsonfield-models-in-graphene-django-308ae43d14ee
class SendFeedbackMutation(graphene.Mutation):
    feedback_response = graphene.Field(FeedbackResponseType)
    errors = graphene.List(
        ErrorType, description="May contain more than one error for same field."
    )

    class Arguments:
        course_session_id = graphene.ID(required=True)
        learning_content_page_id = graphene.ID(required=True)
        learning_content_type = graphene.String(required=True)
        data = GenericScalar()
        submitted = graphene.Boolean(required=False, default_value=False)

    @classmethod
    def mutate(
        cls,
        root,
        info,
        course_session_id,
        learning_content_page_id,
        learning_content_type,
        data,
        submitted,
    ):
        feedback_user_id = info.context.user.id

        if learning_content_type == "learnpath.LearningContentFeedbackVV":
            learningContentFeedbackModel = LearningContentFeedbackVV
            serializerClass = CourseFeedbackSerializerVV
            data["feedback_type"] = "vv"
        elif learning_content_type == "learnpath.LearningContentFeedbackUK":
            learningContentFeedbackModel = LearningContentFeedbackUK
            serializerClass = CourseFeedbackSerializerUK
            data["feedback_type"] = "uk"
        else:
            errors = [
                ErrorType(
                    field="learningContentType", messages="Invalid learningContentType"
                )
            ]
            return SendFeedbackMutation(errors=errors)

        learning_content = learningContentFeedbackModel.objects.get(
            id=learning_content_page_id
        )
        circle = learning_content.get_circle()
        course_session = CourseSession.objects.get(id=course_session_id)

        if not has_course_session_access(
            info.context.user,
            course_session.id,
        ):
            return SendFeedbackMutation(
                errors=[
                    ErrorType(
                        field="send_feedback", messages=["Insufficient permissions"]
                    )
                ]
            )

        logger.info(
            "creating feedback",
            label="feedback",
            feedback_user_id=feedback_user_id,
            circle_title=circle.title,
            course_session_id=course_session_id,
        )

        serializer = serializerClass(data=data)

        if not serializer.is_valid():
            logger.error(
                "creating feedback serializer invalid",
                error_list=serializer.errors,
                label="feedback",
            )
            errors = [
                ErrorType(field=field, messages=msgs)
                for field, msgs in serializer.errors.items()
            ]
            return SendFeedbackMutation(errors=errors)

        feedback_response = update_feedback_response(
            feedback_user=info.context.user,
            course_session=course_session,
            learning_content_feedback_page=learning_content,
            submitted=submitted,
            validated_data=serializer.validated_data,
        )

        return SendFeedbackMutation(feedback_response=feedback_response)


class FeedbackMutation(object):
    send_feedback = SendFeedbackMutation.Field()
