import graphene
from django.db.models import Q
from graphene import relay
from graphene_django import DjangoObjectType

from books.models import Chapter, ContentBlock
from books.schema.interfaces import ChapterInterface
from notes.models import ChapterBookmark
from notes.schema import ChapterBookmarkNode


class ChapterNode(DjangoObjectType):
    bookmark = graphene.Field(ChapterBookmarkNode)
    content_blocks = graphene.List('books.schema.nodes.ContentBlockNode')
    title_hidden_for = graphene.List('users.schema.SchoolClassNode')
    description_hidden_for = graphene.List('users.schema.SchoolClassNode')

    class Meta:
        model = Chapter
        only_fields = [
            'slug', 'title', 'description', 'title_hidden_for', 'description_hidden_for'
        ]
        filter_fields = [
            'slug', 'title',
        ]
        interfaces = (relay.Node, ChapterInterface)

    def resolve_content_blocks(self, info, **kwargs):
        user = info.context.user
        school_classes = user.school_classes.values_list('pk', flat=True)

        by_parent = ContentBlock.get_by_parent(self) \
            .filter(contentblocksnapshot__isnull=True)  # exclude snapshot
        # .prefetch_related('visible_for') \
        # .prefetch_related('hidden_for')

        # don't filter the hidden blocks on the server any more, we do this on the client now, as they are not secret
        default_blocks = Q(user_created=False)
        owned_by_user = Q(user_created=True, owner=user)
        teacher_created_and_visible = Q(Q(user_created=True) & Q(visible_for__pk__in=school_classes))

        if user.can_manage_school_class_content:  # teacher
            return by_parent.filter(default_blocks | owned_by_user | teacher_created_and_visible).distinct()
        else:  # student
            return by_parent.filter(default_blocks | teacher_created_and_visible).distinct()

    def resolve_bookmark(self, info, **kwargs):
        return ChapterBookmark.objects.filter(
            user=info.context.user,
            chapter=self
        ).first()

    @staticmethod
    def resolve_title_hidden_for(parent: Chapter, info, **kwargs):
        return parent.title_hidden_for.all()

    @staticmethod
    def resolve_description_hidden_for(parent: Chapter, info, **kwargs):
        return parent.description_hidden_for.all()
