from typing import Type

import graphene
import structlog
from graphene_django import DjangoObjectType
from graphql import GraphQLError
from rest_framework.exceptions import PermissionDenied

from vbv_lernwelt.course.models import Course, CourseBasePage
from vbv_lernwelt.course.permissions import has_course_access
from vbv_lernwelt.course.schema import CoursePageInterface

logger = structlog.get_logger(__name__)


def resolve_course_page(
    page_model_class: Type[CourseBasePage], root, info, id=None, slug=None
):
    try:
        if id is None and slug is None:
            raise GraphQLError("Either 'id' or 'slug' must be provided.")

        page = None
        if id is not None:
            page = page_model_class.objects.get(pk=id)
        elif slug is not None:
            page = page_model_class.objects.get(slug=slug)

        if page and not has_course_access(
            info.context.user, page.specific.get_course().id
        ):
            raise PermissionDenied("You do not have access to this course.")
        return page

    except PermissionDenied as e:
        raise e
    except Exception as e:
        logger.exception(e)
        raise e


class CourseType(DjangoObjectType):
    learning_path = graphene.Field(CoursePageInterface)

    class Meta:
        model = Course
        fields = ("id", "title", "category_name", "slug")

    def resolve_learning_path(self, info):
        return self.get_learning_path()
