import graphene
from wagtail.models import Page
from books.models import Module, Topic
from books.schema.nodes import ModuleNode
from graphene import relay
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField

from notes.models import Highlight


class NotFoundFailure:
    reason = "Not Found"


class NotFound(graphene.ObjectType):
    reason = graphene.String()


class TopicNode(DjangoObjectType):
    pk = graphene.Int()
    modules = graphene.List(graphene.NonNull("books.schema.nodes.ModuleNode"))
    highlights = graphene.List("notes.schema.HighlightNode")

    class Meta:
        model = Topic
        only_fields = [
            "slug",
            "title",
            "teaser",
            "description",
            "vimeo_id",
            "order",
            "instructions",
        ]
        filter_fields = {
            "slug": ["exact", "icontains", "in"],
            "title": ["exact", "icontains", "in"],
        }
        interfaces = (relay.Node,)

    def resolve_pk(self, *args, **kwargs):
        return self.id

    def resolve_modules(self, *args, **kwargs):
        translations = self.get_translations()
        ids = list(self.get_child_ids())
        for translation in translations:
            ids += list(translation.get_child_ids())
        return Module.objects.filter(id__in=ids).live()

    @staticmethod
    def resolve_highlights(root: Topic, info, **kwargs):
        # todo: is this too expensive, query-wise?
        pages = Page.objects.live().descendant_of(root)
        return Highlight.objects.filter(user=info.context.user).filter(page__in=pages)


class TopicOr404Node(graphene.Union):
    class Meta:
        types = (TopicNode, NotFound)

    @classmethod
    def resolve_type(cls, instance, info):
        if type(instance).__name__ == "Topic":
            return TopicNode
        return NotFound
