import re

from django.db import models
from django.utils.text import slugify
from wagtail.admin.panels import FieldPanel, PageChooserPanel
from wagtail.fields import RichTextField, StreamField
from wagtail.models import Page

from vbv_lernwelt.assignment.models import AssignmentType
from vbv_lernwelt.core.constants import DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER
from vbv_lernwelt.core.model_utils import find_available_slug
from vbv_lernwelt.course.models import CourseBasePage, CoursePage
from vbv_lernwelt.media_library.content_blocks import LearnMediaBlock


class LearningPath(CourseBasePage):
    serialize_field_names = ["children", "course"]
    content_panels = Page.content_panels
    subpage_types = ["learnpath.Circle", "learnpath.Topic"]
    parent_page_types = ["course.CoursePage"]

    class Meta:
        verbose_name = "Learning Path"

    def save(self, clean=True, user=None, log_action=False, **kwargs):
        self.slug = find_available_slug(
            slugify(f"{self.get_parent().slug}-lp", allow_unicode=True),
            ignore_page_id=self.id,
        )
        super(LearningPath, self).save(clean, user, log_action, **kwargs)

    def __str__(self):
        return f"{self.title}"

    def get_frontend_url(self):
        return f"/course/{self.slug.replace('-lp', '')}/learn"

    def get_cockpit_url(self):
        return f"/course/{self.slug.replace('-lp', '')}/cockpit"


class Topic(CourseBasePage):
    serialize_field_names = ["is_visible"]

    is_visible = models.BooleanField(default=True)

    parent_page_types = ["learnpath.LearningPath"]

    panels = [
        FieldPanel("title"),
        FieldPanel("is_visible"),
    ]

    def save(self, clean=True, user=None, log_action=False, **kwargs):
        self.slug = find_slug_with_parent_prefix(self, "topic")
        super(Topic, self).save(clean, user, log_action, **kwargs)

    def get_admin_display_title(self):
        return f"Thema: {self.draft_title}"

    class Meta:
        verbose_name = "Topic"

    def __str__(self):
        return f"{self.title}"


class Circle(CourseBasePage):
    parent_page_types = ["learnpath.LearningPath"]
    subpage_types = [
        "learnpath.LearningSequence",
        "learnpath.LearningUnit",
        "learnpath.LearningContentAssignment",
        "learnpath.LearningContentAttendanceCourse",
        "learnpath.LearningContentFeedback",
        "learnpath.LearningContentLearningModule",
        "learnpath.LearningContentMediaLibrary",
        "learnpath.LearningContentPlaceholder",
        "learnpath.LearningContentRichText",
        "learnpath.LearningContentTest",
        "learnpath.LearningContentVideo",
    ]

    serialize_field_names = [
        "children",
        "description",
        "goals",
    ]

    description = models.TextField(default="", blank=True)

    goals = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)

    content_panels = Page.content_panels + [
        FieldPanel("description"),
        FieldPanel("goals"),
    ]

    def get_frontend_url(self):
        r = re.compile(r"^(?P<coursePart>.+?)-lp-circle-(?P<circlePart>.+?)$")
        m = r.match(self.slug)
        if m is None:
            return "ERROR: could not parse slug"
        return f"/course/{m.group('coursePart')}/learn/{m.group('circlePart')}"

    def save(self, clean=True, user=None, log_action=False, **kwargs):
        self.slug = find_slug_with_parent_prefix(self, "circle")
        super(Circle, self).save(clean, user, log_action, **kwargs)

    class Meta:
        verbose_name = "Circle"

    def __str__(self):
        return f"{self.title}"


class LearningSequence(CourseBasePage):
    serialize_field_names = ["icon"]

    parent_page_types = ["learnpath.Circle"]
    subpage_types = []

    icon = models.CharField(max_length=255, default="it-icon-ls-start")

    content_panels = Page.content_panels + [
        FieldPanel("icon"),
    ]

    class Meta:
        verbose_name = "Learning Sequence"

    def __str__(self):
        return f"{self.title}"

    def get_admin_display_title(self):
        return f"{self.icon} {self.draft_title}"

    def get_admin_display_title_html(self):
        return f"""
          <span style="display: inline-flex; align-items: center; font-size: 1.25rem; font-weight: 700;">
            <{self.icon} style="height: 32px; width: 32px;"></{self.icon}>
            <span style="margin-left: 8px;">{self.draft_title}</span>
          </span>"""

    def get_admin_display_title(self):
        return f"LS: {self.draft_title}"

    def save(self, clean=True, user=None, log_action=False, **kwargs):
        self.slug = find_slug_with_parent_prefix(self, "ls")
        super(LearningSequence, self).save(clean, user, log_action, **kwargs)

    def get_frontend_url(self):
        r = re.compile(
            r"^(?P<coursePart>.+?)-lp-circle-(?P<circlePart>.+?)-ls-(?P<lsPart>.+?)$"
        )
        m = r.match(self.slug)
        if m is None:
            return "ERROR: could not parse slug"
        return f"/course/{m.group('coursePart')}/learn/{m.group('circlePart')}#ls-{m.group('lsPart')}"


class LearningUnit(CourseBasePage):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []
    course_category = models.ForeignKey(
        "course.CourseCategory", on_delete=models.SET_NULL, null=True, blank=True
    )
    title_hidden = models.BooleanField(default=False)

    content_panels = Page.content_panels + [
        FieldPanel("course_category"),
        FieldPanel("title_hidden"),
    ]

    class Meta:
        verbose_name = "Learning Unit"

    def __str__(self):
        return f"{self.title}"

    def save(self, clean=True, user=None, log_action=False, **kwargs):
        course = None
        course_parent_page = self.get_ancestors().exact_type(CoursePage).last()
        if course_parent_page:
            course = course_parent_page.specific.course

        if self.course_category is None and course:
            self.course_category = course.coursecategory_set.filter(
                general=True
            ).first()

        if self.course_category.general:
            self.slug = find_slug_with_parent_prefix(self, "lu")
        else:
            self.slug = find_slug_with_parent_prefix(
                self, "lu", self.course_category.title
            )
        super(LearningUnit, self).save(clean, user, log_action, **kwargs)

    def get_frontend_url(self):
        r = re.compile(
            r"^(?P<coursePart>.+?)-lp-circle-(?P<circlePart>.+?)-lu-(?P<luPart>.+?)$"
        )
        m = r.match(self.slug)
        if m is None:
            return "ERROR: could not parse slug"
        return f"/course/{m.group('coursePart')}/learn/{m.group('circlePart')}#lu-{m.group('luPart')}"

    def get_evaluate_url(self):
        r = re.compile(
            r"^(?P<coursePart>.+?)-lp-circle-(?P<circlePart>.+?)-lu-(?P<luPart>.+?)$"
        )
        m = r.match(self.slug)
        return f"/course/{m.group('coursePart')}/learn/{m.group('circlePart')}/evaluate/{m.group('luPart')}"

    def get_admin_display_title(self):
        return f"LE: {self.draft_title}"

    @classmethod
    def get_serializer_class(cls):
        from vbv_lernwelt.learnpath.serializers import LearningUnitSerializer

        return LearningUnitSerializer

    def get_admin_display_title_html(self):
        return f'<span style="font-weight: 700; font-size: 20px;">{self.draft_title}</span>'


class LearningContent(CourseBasePage):
    class Meta:
        abstract = True

    serialize_field_names = [
        "minutes",
        "description",
        "content_url",
    ]

    minutes = models.PositiveIntegerField(default=15)
    description = RichTextField(blank=True)
    content_url = models.TextField(blank=True)

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("minutes"),
        FieldPanel("content_url"),
        FieldPanel("description"),
    ]

    def get_admin_display_title(self):
        display_title = ""

        # if len(self.contents) > 0:
        #     display_title += f"{self.contents[0].block_type.capitalize()}: "

        display_title += self.draft_title

        return display_title

    def get_admin_display_title_html(self):
        return f"""
          <span style="display: inline-flex; align-items: center;">
            <it-icon-checkbox-unchecked style="height: 24px; width: 24px;"></it-icon-checkbox-unchecked>
            <span style="margin-left: 8px;">{self.get_admin_display_title()}</span>
          </span>"""

    def get_frontend_url(self):
        r = re.compile(
            r"^(?P<coursePart>.+?)-lp-circle-(?P<circlePart>.+?)-lc-(?P<lcPart>.+)$"
        )
        m = r.match(self.slug)
        if m is None:
            return "ERROR: could not parse slug"
        return f"/course/{m.group('coursePart')}/learn/{m.group('circlePart')}/{m.group('lcPart')}"

    def save(self, clean=True, user=None, log_action=False, **kwargs):
        self.slug = find_slug_with_parent_prefix(self, "lc")
        super().save(**kwargs)


class LearningContentAttendanceCourse(LearningContent):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []


class LearningContentVideo(LearningContent):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []


class LearningContentPlaceholder(LearningContent):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []


class LearningContentFeedback(LearningContent):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []


class LearningContentLearningModule(LearningContent):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []


class LearningContentMediaLibrary(LearningContent):
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []


class LearningContentTest(LearningContent):
    serialize_field_names = LearningContent.serialize_field_names + [
        "checkbox_text",
    ]
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []

    checkbox_text = models.TextField(blank=True)

    content_panels = LearningContent.content_panels + [
        FieldPanel("checkbox_text", classname="Text"),
    ]


class LearningContentRichText(LearningContent):
    text = RichTextField(blank=True, features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)

    parent_page_types = ["learnpath.Circle"]
    serialize_field_names = LearningContent.serialize_field_names + [
        "text",
    ]
    subpage_types = []
    content_panels = LearningContent.content_panels + [
        FieldPanel("text", classname="Text"),
    ]


class LearningContentAssignment(LearningContent):
    serialize_field_names = LearningContent.serialize_field_names + [
        "content_assignment_id",
        "assignment_type",
    ]
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []

    content_assignment = models.ForeignKey(
        "assignment.Assignment",
        on_delete=models.PROTECT,
        related_name="+",
    )

    assignment_type = models.CharField(
        max_length=50,
        choices=[(tag.name, tag.name) for tag in AssignmentType],
        default=AssignmentType.CASEWORK.name,
    )

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("minutes"),
        PageChooserPanel("content_assignment", "assignment.Assignment"),
        FieldPanel("content_url"),
        FieldPanel("description"),
    ]


class LearningContentDocumentList(LearningContent):
    serialize_field_names = LearningContent.serialize_field_names + [
        "documents",
    ]
    parent_page_types = ["learnpath.Circle"]
    subpage_types = []

    documents = StreamField(
        [
            ("document", LearnMediaBlock()),
        ],
        use_json_field=True,
        blank=True,
    )

    content_panels = [
        FieldPanel("title", classname="full title"),
        FieldPanel("minutes"),
        FieldPanel("description"),
        FieldPanel("documents"),
    ]


def find_slug_with_parent_prefix(page, type_prefix, slug_postfix=None):
    parent_slug = page.get_ancestors().exact_type(LearningPath, Circle).last().slug
    if parent_slug:
        slug_prefix = f"{parent_slug}-{type_prefix}"
    else:
        slug_prefix = type_prefix

    if slug_postfix is None:
        slug_postfix = page.title

    return find_available_slug(
        slugify(f"{slug_prefix}-{slug_postfix}", allow_unicode=True),
        ignore_page_id=page.id,
    )
