import graphene
from graphene import relay
from rest_framework.exceptions import PermissionDenied

from api.utils import get_object
from books.schema.inputs import UserGroupBlockVisibility
from core.utils import set_visible_for, set_hidden_for
from objectives.inputs import AddObjectiveArgument
from objectives.models import Objective, ObjectiveGroup
from objectives.schema import ObjectiveNode, ObjectiveGroupNode


class UpdateObjectiveVisibility(relay.ClientIDMutation):
    class Input:
        id = graphene.ID(required=True, description='The ID of the objective')
        visibility = graphene.List(UserGroupBlockVisibility)

    objective = graphene.Field(ObjectiveNode)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        objective_id = kwargs.get('id')
        visibility_list = kwargs.get('visibility')
        objective = get_object(Objective, objective_id)  # info.context.user = django user

        if visibility_list is not None:
            if objective.owner is not None:
                set_visible_for(objective, visibility_list)
            else:
                set_hidden_for(objective, visibility_list)

                objective.save()

        return cls(objective=objective)


class UpdateObjectiveGroupVisibility(relay.ClientIDMutation):
    class Input:
        id = graphene.ID(required=True, description='The ID of the objective group')
        visibility = graphene.List(UserGroupBlockVisibility)

    objective_group = graphene.Field(ObjectiveGroupNode)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        objective_group_id = kwargs.get('id')
        visibility_list = kwargs.get('visibility')
        objective_group = get_object(ObjectiveGroup, objective_group_id)  # info.context.user = django user

        if visibility_list is not None:
            set_hidden_for(objective_group, visibility_list)
            objective_group.save()

        return cls(objective_group=objective_group)


class AddObjective(relay.ClientIDMutation):
    class Input:
        objective = graphene.Argument(AddObjectiveArgument)

    objective = graphene.Field(ObjectiveNode)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        owner = info.context.user
        if not owner.has_perm('users.can_manage_school_class_content'):
            raise PermissionDenied('Missing permissions')

        objective_data = kwargs.get('objective')
        objective_group_id = objective_data.get('objective_group')
        text = objective_data.get('text')

        objective_group = get_object(ObjectiveGroup, objective_group_id)

        objective = Objective.objects.create(text=text, owner=owner, group=objective_group)

        return cls(objective=objective)


class DeleteObjective(relay.ClientIDMutation):
    class Input:
        id = graphene.ID(required=True)

    success = graphene.Boolean()

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        id = kwargs.get('id')

        objective = get_object(Objective, id)
        user = info.context.user

        if not user.has_perm('users.can_manage_school_class_content'):
            raise PermissionDenied('Missing permissions')
        if objective.owner.pk != user.pk:
            raise PermissionDenied('Permission denied: Not owner')

        objective.delete()
        return cls(success=True)


class ObjectiveMutations:
    update_objective_visibility = UpdateObjectiveVisibility.Field()
    update_objective_group_visibility = UpdateObjectiveGroupVisibility.Field()
    add_objective = AddObjective.Field()
    delete_objective = DeleteObjective.Field()
