import datetime

from django.db import models
from django.utils import timezone
from wagtail.models import Page

from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import CourseSession


class DueDate(models.Model):
    start = models.DateTimeField(
        null=True, db_index=True, help_text="Startdatum ist Pflicht"
    )
    end = models.DateTimeField(
        null=True, blank=True, db_index=True, help_text="Enddatum ist optional"
    )
    manual_override_fields = models.BooleanField(
        default=False,
        help_text="Nur aktivieren, wenn man die Felder manuell überschreiben will",
    )
    title = models.CharField(
        default="",
        max_length=1024,
        help_text="Title wird standarmässig vom LearningContent übernommen",
    )
    assignment_type_translation_key = models.CharField(
        default="",
        blank=True,
        max_length=1024,
        help_text="Translation Key aus dem Frontend",
    )
    date_type_translation_key = models.CharField(
        default="",
        blank=True,
        max_length=1024,
        help_text="Translation Key aus dem Frontend",
    )
    subtitle = models.TextField(
        default="",
        blank=True,
        help_text="Überschreibt den Untertitel bei `assignment_type_translation_key` und `date_type_translation_key`",
    )
    url = models.CharField(
        default="",
        blank=True,
        max_length=1024,
        help_text="URL wird vom LearningContent übernommen (sichtbar für Member/Teilnehmer)",
    )
    url_expert = models.CharField(
        default="",
        blank=True,
        max_length=1024,
        help_text="URL wird aus dem LearningContent generiert (sichtbar für den Experten/Trainer)",
    )
    course_session = models.ForeignKey(
        "course.CourseSession",
        on_delete=models.CASCADE,
        blank=True,
    )

    page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True, blank=True)
    circle_data = models.JSONField(default=dict, blank=True)

    class Meta:
        ordering = ["start", "end"]

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

        # Convert the UTC datetime to local time
        local_start = timezone.localtime(self.start) if self.start else None
        start_str = local_start.strftime("%Y-%m-%d %H:%M") if local_start else "-"
        result = f"{self.title} {start_str}"

        if self.end:
            local_end = timezone.localtime(self.end) if self.end else None
            end_str = local_end.strftime("%Y-%m-%d %H:%M") if local_end else "-"
            result += f" - {end_str}"

        return result

    def save(self, *args, **kwargs):
        try:
            circle = self.get_circle()
            # prefetch circle data, because loading it dynamically is too slow
            if circle:
                self.circle_data = {
                    "id": str(circle.id),
                    "title": circle.title,
                    "slug": circle.slug,
                }
        except Exception:
            # noop
            pass
        super().save(*args, **kwargs)

    @property
    def display_subtitle(self):
        result = ""
        if self.subtitle and self.manual_override_fields:
            result = self.subtitle

        result = self.assignment_type_translation_key

        if self.date_type_translation_key:
            result += ": " + self.date_type_translation_key

        return result

    @property
    def is_undefined(self):
        return self.start is None

    @property
    def duration(self):
        if self.end is None:
            return datetime.timedelta(0)
        return self.end - self.start

    def get_circle(self):
        try:
            return self.page.specific.get_circle()
        except Exception:
            # noop
            return None

    @classmethod
    def get_users_next_events_qs(
        cls, user: User, course_session: CourseSession = None, limit=10
    ):
        """
        Returns a queryset of all due dates that are relevant for the given user.
        If course_session is given, only due dates for that course_session are returned.
        The user is determined by via a course session user of a course_assignment.

        """
        qs = cls.get_next_due_dates_qs()

        if course_session:
            qs = qs.filter(
                course_session=course_session,
                course_session__course_assignment__user=user,
            )
        else:
            qs = qs.filter(course_session__course_assignment__user=user)

        qs = qs.order_by("start")[:limit]

        return qs

    @classmethod
    def get_next_due_dates_qs(cls):
        now = timezone.now()
        qs = cls.objects.filter(start__gte=now)
        return qs
