from django.db import models
from django.template.defaultfilters import slugify
from django.urls import reverse
from django.utils import timezone


class Event(models.Model):
    title = models.CharField(max_length=180)
    slug = models.SlugField(unique=True, max_length=200, blank=True)
    summary = models.CharField(max_length=260)
    description = models.TextField()
    venue = models.CharField(max_length=180)
    start_at = models.DateTimeField()
    end_at = models.DateTimeField()
    capacity = models.PositiveIntegerField(blank=True, null=True)
    is_published = models.BooleanField(default=True)
    registration_opens = models.DateTimeField(blank=True, null=True)
    registration_closes = models.DateTimeField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['start_at']

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        if not self.slug:
            base_slug = slugify(self.title)[:180] or 'event'
            slug = base_slug
            counter = 2
            while Event.objects.exclude(pk=self.pk).filter(slug=slug).exists():
                slug = f'{base_slug}-{counter}'[:200]
                counter += 1
            self.slug = slug
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('event_detail', args=[self.slug])

    @property
    def confirmed_registrations_count(self):
        return self.registrations.filter(status=Registration.Status.CONFIRMED).count()

    @property
    def waitlist_count(self):
        return self.registrations.filter(status=Registration.Status.WAITLIST).count()

    @property
    def spots_remaining(self):
        if self.capacity is None:
            return None
        return max(self.capacity - self.confirmed_registrations_count, 0)

    @property
    def registration_is_open(self):
        now = timezone.now()
        if not self.is_published:
            return False
        if self.registration_opens and now < self.registration_opens:
            return False
        if self.registration_closes and now > self.registration_closes:
            return False
        return True


class Registration(models.Model):
    class Status(models.TextChoices):
        CONFIRMED = 'confirmed', 'Confirmed'
        WAITLIST = 'waitlist', 'Waitlist'

    event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='registrations')
    full_name = models.CharField(max_length=160)
    email = models.EmailField()
    company = models.CharField(max_length=160, blank=True)
    notes = models.TextField(blank=True)
    status = models.CharField(max_length=24, choices=Status.choices, default=Status.CONFIRMED)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ['created_at']
        constraints = [
            models.UniqueConstraint(fields=['event', 'email'], name='unique_registration_per_event_email'),
        ]

    def __str__(self):
        return f'{self.full_name} · {self.event.title}'
