from datetime import date
from django.conf import settings
from django.core.validators import ValidationError
from django.contrib.auth.models import User
from django.db import models
from django.db.models import F
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
from .managers import TaskManager


class TaskList(models.Model):
    name = models.CharField(max_length=128)

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

    users = models.ManyToManyField(User, blank=True)

    objects = models.Manager()

    class Meta:
        verbose_name = "Auf­ga­ben­be­reich"
        verbose_name_plural = "Auf­ga­ben­be­reiche"

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("tasks:index")

    def clean(self):
        if not self.shortterm:
            self.shortterm = slugify(self.name)
        self.slug = slugify(self.shortterm)


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

    shortterm = models.CharField(max_length=25, blank=True)
    slug = models.SlugField(max_length=25, blank=True)

    task_list = models.ForeignKey(
        TaskList, verbose_name="Aufgabenbereich", on_delete=models.CASCADE, null=True
    )

    created_date = models.DateTimeField(auto_now_add=True)
    due_date = models.DateField(verbose_name="Fälligkeit", blank=True, null=True)

    completed = models.BooleanField(verbose_name="Abgeschlossen", default=False)
    completed_date = models.DateField(blank=True, null=True)

    created_by = models.ForeignKey(
        User,
        related_name="created_by",
        on_delete=models.CASCADE,
    )
    assigned_to = models.ForeignKey(
        User,
        blank=True,
        null=True,
        related_name="assigned_to",
        on_delete=models.CASCADE,
        verbose_name="Zugewiesen an",
    )

    note = models.TextField(verbose_name="Notizen", blank=True, null=True)
    priority = models.PositiveIntegerField(
        verbose_name="Priorität", blank=True, null=True
    )

    objects = models.Manager()
    taskmanager = TaskManager()

    class Meta:
        ordering = ("task_list", F("due_date").desc(nulls_first=True))
        verbose_name = "Aufgabe"
        verbose_name_plural = "Aufgaben"

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("tasks:task-detail", kwargs={"pk": self.id})

    def clean(self):
        if not self.shortterm:
            self.shortterm = slugify(self.title[:25])
        self.slug = slugify(self.shortterm)

    def save(self, *args, **kwargs):
        if self.completed and not self.completed_date:
            self.completed_date = timezone.now().date()

        if not self.completed and self.completed_date:
            self.completed_date = None

        super().save(*args, **kwargs)


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

    shortterm = models.CharField(max_length=20, blank=True)
    slug = models.SlugField(max_length=20, blank=True)

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

    task = models.ForeignKey(Task, on_delete=models.CASCADE)

    objects = models.Manager()

    class Meta:
        verbose_name = "Dokument"
        verbose_name_plural = "Dokumente"

        constraints = [
            # TODO: include lower/upper case - when Django 4.0, then go for it.
            UniqueConstraint(
                fields=["title", "date", "task"], name="unique_task_document"
            ),
        ]

    def clean(self):
        if not self.shortterm:
            self.shortterm = slugify(self.title[:20])
        self.slug = slugify(self.shortterm)

        pad_name = slugify(str(self.date) + "-" + self.task.slug + "-" + self.slug)
        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."),
            )

    def __str__(self):
        return self.title
