"""Calendar domain models.

Model inventory
---------------
CalendarEvent     — tenant-scoped event with time range, owner, attendees
EventAttendee     — user/external attendee on a CalendarEvent
EventLinkedObject — generic link from a CalendarEvent to any domain object
"""

from __future__ import annotations

from typing import ClassVar

from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.utils.translation import gettext_lazy as _

from simorgh.core.models import (
    TenantScopedModel,
    TimeStampedModel,
    UUIDModel,
)


# ---------------------------------------------------------------------------
# Choices
# ---------------------------------------------------------------------------

class AttendeeStatus(models.TextChoices):
    PENDING = "pending", _("Pending")
    ACCEPTED = "accepted", _("Accepted")
    DECLINED = "declined", _("Declined")


# ---------------------------------------------------------------------------
# CalendarEvent
# ---------------------------------------------------------------------------

class CalendarEvent(UUIDModel, TenantScopedModel):
    """A tenant-scoped calendar event owned by a user."""

    title = models.CharField(_("title"), max_length=255, db_index=True)
    description = models.TextField(_("description"), blank=True, default="")
    location = models.CharField(_("location"), max_length=255, blank=True, default="")
    start_dt = models.DateTimeField(_("start datetime"), db_index=True)
    end_dt = models.DateTimeField(_("end datetime"), db_index=True)
    all_day = models.BooleanField(_("all day"), default=False)
    owner = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="owned_calendar_events",
        verbose_name=_("owner"),
    )
    color = models.CharField(_("color"), max_length=32, blank=True, default="")
    is_recurring = models.BooleanField(_("is recurring"), default=False)

    class Meta:
        verbose_name = _("calendar event")
        verbose_name_plural = _("calendar events")
        ordering: ClassVar[list[str]] = ["start_dt"]
        indexes: ClassVar[list[models.Index]] = [
            models.Index(fields=("tenant", "owner", "start_dt")),
        ]

    def __str__(self) -> str:
        return f"{self.title} ({self.start_dt})"


# ---------------------------------------------------------------------------
# EventAttendee
# ---------------------------------------------------------------------------

class EventAttendee(UUIDModel, TimeStampedModel):
    """A person invited to a CalendarEvent — either a platform user or external email."""

    event = models.ForeignKey(
        CalendarEvent,
        on_delete=models.CASCADE,
        related_name="attendees",
        verbose_name=_("event"),
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="event_attendances",
        verbose_name=_("user"),
    )
    external_email = models.EmailField(_("external email"), blank=True, default="")
    status = models.CharField(
        _("status"),
        max_length=16,
        choices=AttendeeStatus.choices,
        default=AttendeeStatus.PENDING,
    )

    class Meta:
        verbose_name = _("event attendee")
        verbose_name_plural = _("event attendees")
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("event", "user"),
                condition=models.Q(user__isnull=False),
                name="cal_attendee_unique_user_per_event",
            ),
        ]

    def __str__(self) -> str:
        return f"{self.event_id}:{self.user_id or self.external_email}"


# ---------------------------------------------------------------------------
# EventLinkedObject
# ---------------------------------------------------------------------------

class EventLinkedObject(UUIDModel, TimeStampedModel):
    """A generic link from a CalendarEvent to any domain object (Lead, Opportunity, Task…)."""

    event = models.ForeignKey(
        CalendarEvent,
        on_delete=models.CASCADE,
        related_name="linked_objects",
        verbose_name=_("event"),
    )
    content_type = models.ForeignKey(
        ContentType,
        on_delete=models.CASCADE,
        verbose_name=_("content type"),
    )
    object_id = models.PositiveIntegerField(_("object id"))
    linked = GenericForeignKey("content_type", "object_id")

    class Meta:
        verbose_name = _("event linked object")
        verbose_name_plural = _("event linked objects")
        constraints: ClassVar[list[models.BaseConstraint]] = [
            models.UniqueConstraint(
                fields=("event", "content_type", "object_id"),
                name="cal_linked_unique_per_event",
            ),
        ]

    def __str__(self) -> str:
        return f"{self.event_id} → {self.content_type_id}:{self.object_id}"
