
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from django.contrib.auth import get_user_model
from django.utils.safestring import mark_safe, SafeText
from django.utils.html import escape
from django.urls import reverse
from tinywiki.enums import (
    WIKI_CONTENT_TYPES,
    WIKI_PAGE_STATUS,
    WikiContentType,
    WikiPageStatus,
)
import markdown

import bbcode as _bbcode
from tinywiki.parser import bbcode

from .parser import parse_bbcode
from . import settings
import tinywiki


def get_tinywiki_default_user():
    UserModel = get_user_model()
    try:
        user = UserModel.objects.get(**settings.TINYWIKI_USER_LOOKUP)
    except UserModel.DoesNotExist:
        user = UserModel.objects.filter(is_superuser=True).order_by('pk')[0]
    return user


class Page(models.Model):
    slug = models.SlugField(_("slug"),
                            max_length=255,
                            null=False,
                            blank=False,
                            unique=True)
    title = models.CharField(_("title"),
                             max_length=255,
                             null=False,
                             blank=False)
    author = models.ForeignKey(get_user_model(),
                               on_delete=models.SET_DEFAULT,
                               default=get_tinywiki_default_user,
                               verbose_name=_("author"),
                               related_name="tinywiki_athors")
    status_data = models.CharField(_("status"),
                                   choices=[(i.value,i.str_lazy) for i in WIKI_PAGE_STATUS],
                                   max_length=15,
                                   null=False,
                                   blank=False,
                                   default=WikiPageStatus.IN_PROGRESS.value)
    content_type_data = models.CharField(_("content type"),
                                         choices=[(i.value,i.str_lazy) for i in WIKI_CONTENT_TYPES],
                                         default=WikiContentType.BBCODE.value)

    content = models.TextField(_("Page content"),
                               null=False,
                               blank=False)


    created_at = models.DateTimeField(_("created at"),
                                      auto_now_add=True)
    created_by = models.ForeignKey(get_user_model(),
                                   on_delete=models.SET_DEFAULT,
                                   verbose_name=_("created by"),
                                   default=get_tinywiki_default_user,
                                   related_name="tinywiki_created")

    last_edited_at = models.DateTimeField(_("last edited at"),
                                          auto_now=True)
    last_edited_by = models.ForeignKey(get_user_model(),
                                       on_delete=models.SET_DEFAULT,
                                       verbose_name=_("last edited by"),
                                       default=get_tinywiki_default_user,
                                       related_name="tinywiki_last_edited")

    @property
    def content_type(self)->WikiContentType:
        return WikiContentType.from_string(self.content_type_data)
    @content_type.setter
    def content_type(self, content_type: str | WikiContentType):
        if isinstance(content_type, str):
            self.content_type_data = WikiContentType.from_string(content_type).value
        elif isinstance(content_type, WikiContentType):
            self.content_type_data = content_type.value
        else:
            raise TypeError("content_type")

    @property
    def status(self)->WikiPageStatus:
        return WikiPageStatus.from_string(self.status_data)
    @status.setter
    def status(self, status: str | WikiPageStatus):
        if isinstance(status, str):
            self.status_data = WikiPageStatus.from_string(status).value
        elif isinstance(status, WikiPageStatus):
            self.status_data = status.value
        else:
            raise TypeError("status")

    @property
    def html_content(self) -> SafeText | str:
        if self.content_type == WikiContentType.MARKDOWN:
            return mark_safe(markdown.markdown(self.content))
        elif self.content_type == WikiContentType.BBCODE:
            return mark_safe(parse_bbcode(self.content))
        return self.content


class Image(models.Model):
    models.ManyToManyField(Page, verbose_name=_(""))
    slug = models.SlugField(_("slug"),
                            max_length=255)
    alt = models.CharField(_("alternative text"),
                           max_length=511,
                           null=False,
                           blank=False)
    description = models.CharField(_("description"),
                                   max_length=1023,
                                   null=True,
                                   blank=True)
    image = models.ImageField(_("image file"),
                              upload_to="tinywiki/img")

    uploaded_by = models.ForeignKey(get_user_model(),
                                    on_delete=models.SET_DEFAULT,
                                    verbose_name=_("uploaded by"),
                                    default=get_tinywiki_default_user,
                                    related_name="tinywiki_image_uploads")
    uploaded_at = models.DateTimeField(_("uploaded at"),
                                       auto_now_add=True)

    @property
    def description_html(self) -> str:
        return _bbcode.render_html(self.description)

    @property
    def description_html_safe(self) -> SafeText:
        return mark_safe(self.description_html)


class SidebarSection(models.Model):
    title = models.CharField(_("title"),
                             max_length=255,
                             null=False,
                             blank=False)
    priority = models.PositiveIntegerField(_("priority"))
    is_visible = models.BooleanField(_("is visible"),
                                     default=True)

    @property
    def widget(self) -> SafeText:
        if settings.USE_BOOTSTRAP:
            lines = [
                "<ul class=\"list-group mt-2\">",
                f"<li class=\"list-group-item bg-primary text-white\">{escape(self.title)}</li>",  # noqa: E501
                *[item.item for item in self.items.filter(is_visible=True).order_by('-priority')],  # noqa: E501
                "</ul>"
            ]
        else:
            lines = [
                "<ul class=\"sidebar-section\">",
                f"<li class=\"sidebar-title\">{escape(self.title)}</li>",
                *[item.item for item in self.items.filter(is_visible=True).order_by('-priority')],  # noqa: E501
                "</ul>"
            ]
        return mark_safe("\n".join(lines))


class SidebarEntry(models.Model):
    section = models.ForeignKey(SidebarSection,
                                on_delete=models.CASCADE,
                                verbose_name=_("Section"),
                                related_name="items")
    title = models.CharField(_("Title"),
                             max_length=255,
                             null=False,
                             blank=False)
    is_visible = models.BooleanField(_("is visible"),
                                     default=True)
    priority = models.PositiveIntegerField(_("Priority"))
    wiki_slug = models.CharField(_("Wiki slug"),
                                 max_length=255,
                                 null=True,
                                 blank=True)
    url = models.CharField(_("Link URL"),
                           max_length=512,
                           null=True,
                           blank=True)

    widget = models.TextField(_("Widget"),
                              blank=True,
                              null=True)

    @property
    def link(self) -> SafeText:
        if self.wiki_slug:
            return mark_safe(f"<a href=\"{reverse('tinywiki:page', kwargs={'slug': self.wiki_slug})}\">{escape(self.title)}</a>")  # noqa: E501
        elif self.url:
            return mark_safe(f"<a href=\"{self.url}\">{escape(self.title)}</a>")  # noqa E501
        return mark_safe(f"<a href=\"#\">{escape(self.title)}</a>")  # noqa E501

    @property
    def item(self) -> SafeText:
        if settings.USE_BOOTSTRAP:
            if self.widget:
                return mark_safe(f"<li class=\"list-group-item\">{self.widget}</li>")  # noqa: E501
            else:
                return mark_safe(f"<li class=\"list-group-item\">{self.link}</li>")  # noqa: E501

        if self.widget:
            return mark_safe(f"<li class=\"sidebar-item\">{self.widget}</li>")
        else:
            return mark_safe(f"<li class=\"sidebar-item\">{self.link}</li>")
