import graphene
from basicknowledge.models import BasicKnowledge
from books.models import ContentBlock
from books.schema.interfaces.contentblock import ContentBlockInterface
from books.utils import are_solutions_enabled_for
from core.logger import get_logger
from core.mixins import HiddenAndVisibleForMixin
from graphene import relay
from graphene_django import DjangoObjectType
from notes.models import ContentBlockBookmark
from rooms.models import ModuleRoomSlug

logger = get_logger(__name__)


class TextBlockNode(graphene.ObjectType):
    text = graphene.String()

    def resolve_text(root, info, **kwargs):
        return root["value"]["text"]


class ContentNode(graphene.Union):
    class Meta:
        types = (TextBlockNode,)

    @classmethod
    def resolve_type(cls, instance, info):
        logger.info(instance)
        if instance["type"] == "text_block":
            return TextBlockNode


def is_solution_and_hidden_for_user(type, user, module):
    return type == "solution" and not (
        are_solutions_enabled_for(user, module) or user.is_teacher()
    )


class ContentBlockNode(DjangoObjectType, HiddenAndVisibleForMixin):
    mine = graphene.Boolean()
    bookmarks = graphene.List("notes.schema.ContentBlockBookmarkNode")
    original_creator = graphene.Field("users.schema.PublicUserNode")
    instrument_category = graphene.Field(
        "basicknowledge.queries.InstrumentCategoryNode"
    )
    path = graphene.String()
    highlights = graphene.List("notes.schema.HighlightNode")

    class Meta:
        model = ContentBlock
        only_fields = [
            "slug",
            "title",
            "type",
            "contents",
            "hidden_for",
            "visible_for",
            "user_created",
        ]
        filter_fields = [
            "slug",
            "title",
        ]
        interfaces = (
            relay.Node,
            ContentBlockInterface,
        )
        convert_choices_to_enum = False

    def resolve_mine(parent, info, **kwargs):
        return parent.owner is not None and parent.owner.pk == info.context.user.pk

    @staticmethod
    def resolve_contents(self: ContentBlock, info, **kwargs):
        updated_raw_data = []
        for content in self.contents.raw_data:
            # only show solutions to teachers and students for whom their teachers have them enabled
            if is_solution_and_hidden_for_user(
                content["type"], info.context.user, self.module
            ):
                logger.debug("Solution is hidden for this user")
                continue

            if content["type"] == "content_list_item":
                _values = []
                for index, list_block in enumerate(content["value"]):
                    if is_solution_and_hidden_for_user(
                        list_block["type"], info.context.user, self.module
                    ):
                        logger.debug("Solution is hidden for this user")
                        continue
                    _values.append(process_module_room_slug_block(list_block))
                content["value"] = _values

            content = process_module_room_slug_block(content)
            updated_raw_data.append(content)

        self.contents.raw_data = updated_raw_data
        return self.contents

    def resolve_bookmarks(self, info, **kwargs):
        return ContentBlockBookmark.objects.filter(
            user=info.context.user, content_block=self
        )

    @staticmethod
    def resolve_instrument_category(root: ContentBlock, info, **kwargs):
        if root.type == ContentBlock.INSTRUMENT:
            for content in root.contents.raw_data:
                if (
                    content["type"] == "instrument"
                    or content["type"] == "basic_knowledge"
                ):
                    _id = content["value"]["basic_knowledge"]
                    instrument = BasicKnowledge.objects.get(id=_id)
                    category = instrument.new_type.category
                    return category
        return None

    @staticmethod
    def resolve_path(root: ContentBlock, info, **kwargs):
        return root.route

    @staticmethod
    def resolve_highlights(root: ContentBlock, info, **kwargs):
        return root.highlights.filter(user=info.context.user)


def process_module_room_slug_block(content):
    if content["type"] == "module_room_slug":
        try:
            module_room_slug = ModuleRoomSlug.objects.get(
                title=content["value"]["title"]
            )
            content["value"] = {
                "title": content["value"]["title"],
                "slug": module_room_slug.slug,
            }
        except ModuleRoomSlug.DoesNotExist:
            pass
    return content
