import logging
from datetime import date
from pathlib import Path

from django.core.validators import ValidationError
from django.db import models
from django.db.models.constraints import UniqueConstraint
from django.urls import reverse
from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _

from documents import create_pad, get_pad_html
from documents.api import get_pad_link
from tasks.models import TaskList

logger = logging.getLogger(__name__)


class TopicGroup(models.Model):
    title = models.CharField(verbose_name="Titel", max_length=128)

    shortterm = models.CharField(max_length=10, unique=True)
    slug = models.SlugField(max_length=10, unique=True)

    short_description = models.TextField(null=True, blank=True)

    order = models.PositiveSmallIntegerField(
        verbose_name="Reihenfolge", unique=True, null=True, blank=True
    )

    objects = models.Manager()

    class Meta:
        verbose_name = "Themenbereich"
        # "1." because this point should be displayed first in admin view.
        verbose_name_plural = "Themenbereiche"

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("intern:index") + "#" + self.slug

    def clean(self, *args, **kwargs):
        self.slug = slugify(self.shortterm)


class Topic(models.Model):
    title = models.CharField(verbose_name="Titel", max_length=128)

    shortterm = models.CharField(max_length=10, unique=True)
    slug = models.SlugField(max_length=10, unique=True)

    archive = models.BooleanField(verbose_name="Archiv", default=False)

    description = models.TextField(null=True, blank=True)

    topic_group = models.ForeignKey(
        TopicGroup, on_delete=models.CASCADE, verbose_name="Themenbereich"
    )
    task_list = models.ForeignKey(
        TaskList, on_delete=models.CASCADE, null=True, blank=True
    )

    objects = models.Manager()

    class Meta:
        verbose_name = "Thema"
        verbose_name_plural = "Themen"

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("intern:topic", kwargs={"slug": self.slug})

    def clean(self, *args, **kwargs):
        self.slug = slugify(self.shortterm)


class Attachment(models.Model):
    title = models.CharField(verbose_name="Titel", max_length=128)

    shortterm = models.CharField(max_length=10)
    slug = models.SlugField(max_length=10)

    description = models.TextField(null=True, blank=True)

    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)

    objects = models.Manager()

    class Meta:
        verbose_name = "Anhang Ordner"
        verbose_name_plural = "Anhang Ordner"

        constraints = [
            UniqueConstraint(fields=["slug", "topic"], name="unique_intern_slug_topic"),
            UniqueConstraint(
                fields=["title", "topic"], name="unique_intern_title_topic"
            ),
        ]

    def __str__(self):
        return self.topic.title + " / " + self.title

    def get_absolute_url(self):
        kwargs = {
            "topic_slug": self.topic.slug,
            "slug": self.slug,
        }

        return reverse("intern:attachment", kwargs=kwargs)

    def clean(self, *args, **kwargs):
        self.slug = slugify(self.shortterm)


class Etherpad(models.Model):
    title = models.CharField(verbose_name="Titel", max_length=128)
    slug = models.SlugField(null=True, blank=True)

    etherpad_key = models.CharField(max_length=50, blank=True)
    date = models.DateField(verbose_name="Datum", default=date.today)

    attachment = models.ForeignKey(Attachment, on_delete=models.CASCADE)

    objects = models.Manager()

    class Meta:
        verbose_name = "Etherpad"
        verbose_name_plural = "Etherpads"

        constraints = [
            UniqueConstraint(
                fields=["title", "date", "attachment"], name="unique_intern_etherpad"
            ),
        ]

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return get_pad_link(self.__get_pad_name())

    def __get_pad_name(self):
        return (
            slugify(self.date)
            + "-"
            + self.attachment.topic.slug
            + "-"
            + self.attachment.slug
            + "-"
            + self.slug
        )

    def clean(self):
        self.slug = slugify(self.title)

        if not self.etherpad_key:
            pad_name = self.__get_pad_name()
            if len(pad_name) > 50:
                raise ValidationError(
                    _(
                        "Name zum Erstellen des Etherpads ist zu lange - max. 50 Zeichen. (Länge: %(length)s, Name: %(pad_name)s)"
                    ),
                    params={"length": len(pad_name), "pad_name": pad_name},
                )

            self.etherpad_key = create_pad(pad_name)
            if not self.etherpad_key:
                raise ValidationError(
                    _(f"Etherpad '{pad_name}' konnte nicht erstellt werden."),
                )

    @property
    def etherpad_html(self):
        if not self.__get_pad_name():
            return None

        return get_pad_html(self.__get_pad_name())


class FileUpload(models.Model):
    title = models.CharField(verbose_name="Titel", max_length=128, blank=True)
    file_field = models.FileField(
        verbose_name="Dokument", upload_to="uploads/intern/files/"
    )
    date = models.DateField(verbose_name="Datum", default=date.today)

    attachment = models.ForeignKey(Attachment, on_delete=models.CASCADE)

    objects = models.Manager()

    class Meta:
        verbose_name = "Datei"
        verbose_name_plural = "Dateien"

    def __str__(self):
        return self.title

    def clean(self):
        if not self.title:
            self.title = Path(self.file_field.name).stem
