from datetime import datetime

import graphene
from graphene import relay

from api.utils import get_object
from books.models import Module, RecentModule
from books.schema.nodes import ModuleNode
from users.models import SchoolClass


class UpdateSolutionVisibility(relay.ClientIDMutation):
    class Input:
        slug = graphene.String()
        enabled = graphene.Boolean()

    success = graphene.Boolean()
    solutions_enabled = graphene.Boolean()
    errors = graphene.List(graphene.String)

    @classmethod
    def mutate_and_get_payload(cls, root, info, **args):
        try:
            slug = args.get('slug')
            enabled = args.get('enabled')
            user = info.context.user
            selected_class = user.selected_class
            if 'users.can_manage_school_class_content' not in user.get_role_permissions():
                raise PermissionError()

            module = Module.objects.get(slug=slug)
            if enabled:
                module.solutions_enabled_for.add(selected_class)
            else:
                module.solutions_enabled_for.remove(selected_class)
            module.save()

            return cls(success=True, solutions_enabled=enabled)

        except PermissionError:
            errors = ["You don't have the permission to do that."]
        except Exception as e:
            errors = ['Error: {}'.format(e)]

        return cls(success=False, solutions_enabled=None, errors=errors)


class UpdateLastModule(relay.ClientIDMutation):
    class Input:
        # todo: use slug here too
        id = graphene.ID()

    last_module = graphene.Field(ModuleNode)

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

        module = get_object(Module, id)
        if not module:
            raise Module.DoesNotExist

        try:
            same_module = RecentModule.objects.get(user=user, module=module)
            same_module.visited = datetime.now()
            same_module.save()
            return cls(last_module=same_module.module)
        except RecentModule.DoesNotExist:
            recent_modules = RecentModule.objects.filter(user=user)
            while recent_modules.all().count() >= 3:
                recent_modules.earliest().delete()

            last_module = RecentModule.objects.create(user=user, module=module)

            return cls(last_module=last_module.module)


class SyncModuleVisibility(relay.ClientIDMutation):
    class Input:
        module = graphene.String(required=True)
        template_school_class = graphene.ID(required=True)
        school_class = graphene.ID(required=True)

    success = graphene.Boolean()

    @classmethod
    def mutate_and_get_payload(cls, root, info, **args):
        user = info.context.user
        if not user.is_teacher():
            raise Exception('Permission denied')

        module_slug = args.get('module')
        template_id = args.get('template_school_class')
        school_class_id = args.get('school_class')

        module = Module.objects.get(slug=module_slug)
        template = get_object(SchoolClass, template_id)
        school_class = get_object(SchoolClass, school_class_id)
        if not template.is_user_in_schoolclass(user) or not school_class.is_user_in_schoolclass(user):
            raise Exception('Permission denied')

        module.sync_from_school_class(template, school_class)

        return cls(success=True)
