from __future__ import annotations

from django.conf import settings
from django.db import models
from simple_history.models import HistoricalRecords

from apps.alumni.profiles.models import AlumniProfile
from apps.core.storage.paths import upload_to_alumni_photos


class SpotlightCategory(models.TextChoices):
    PARTNER_OF_YEAR = "partner_of_year", "Partner of the Year"
    MENTOR_OF_MONTH = "mentor_of_month", "Mentor of the Month"
    INNOVATOR = "innovator", "Innovator spotlight"
    NEWSLETTER = "newsletter", "Newsletter feature"


class Spotlight(models.Model):
    """A curated recognition published by an alumni officer.

    Each (category, period_label) pair has at most one active spotlight —
    publishing a new one deactivates the prior winner via the service layer.
    """

    profile = models.ForeignKey(
        AlumniProfile,
        on_delete=models.CASCADE,
        related_name="spotlights",
    )
    category = models.CharField(max_length=24, choices=SpotlightCategory.choices)
    title = models.CharField(max_length=200)
    citation = models.TextField(help_text="Curator's writeup of why this alumna/us is being recognised.")
    cover_image = models.FileField(
        upload_to=upload_to_alumni_photos, blank=True, null=True
    )
    period_label = models.CharField(
        max_length=16,
        db_index=True,
        help_text="Reporting period, e.g. '2026' or '2026-04'.",
    )
    featured_from = models.DateField()
    featured_until = models.DateField()
    is_active = models.BooleanField(default=True, db_index=True)
    nominated_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="alumni_spotlights_nominated",
    )
    curated_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT,
        related_name="alumni_spotlights_curated",
    )
    created_at = models.DateTimeField(auto_now_add=True)

    history = HistoricalRecords()

    class Meta:
        ordering = ["-featured_from"]
        constraints = [
            models.UniqueConstraint(
                fields=["category", "period_label"],
                name="uniq_spotlight_per_category_period",
            ),
        ]
        indexes = [
            models.Index(fields=["is_active", "featured_from"]),
        ]

    def __str__(self):
        return f"{self.get_category_display()} — {self.title}"


class Endorsement(models.Model):
    """A community nomination. One endorsement per (profile, endorser, category, period)."""

    profile = models.ForeignKey(
        AlumniProfile,
        on_delete=models.CASCADE,
        related_name="endorsements_received",
    )
    endorser = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="alumni_endorsements_given",
    )
    category = models.CharField(max_length=24, choices=SpotlightCategory.choices)
    citation = models.CharField(max_length=400, blank=True)
    period_label = models.CharField(max_length=16, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]
        constraints = [
            models.UniqueConstraint(
                fields=["profile", "endorser", "category", "period_label"],
                name="uniq_endorsement_per_period",
            ),
        ]

    def __str__(self):
        return f"{self.endorser_id}→{self.profile_id} ({self.category}/{self.period_label})"


class BroadcastAudience(models.TextChoices):
    ALL_OPTED_IN = "all_opted_in", "All opted-in alumni"
    MENTORS = "mentors", "Mentors accepting mentees"
    BY_GROUP = "by_group", "Members of selected groups"
    BY_COUNTRY = "by_country", "By country"
    BY_GRADUATION_YEAR = "by_graduation_year", "By graduation year"
    BY_PROGRAMME = "by_programme", "By programme name"


class BroadcastStatus(models.TextChoices):
    DRAFT = "draft", "Draft"
    SCHEDULED = "scheduled", "Scheduled"
    SENDING = "sending", "Sending"
    SENT = "sent", "Sent"
    FAILED = "failed", "Failed"


class Broadcast(models.Model):
    """An officer-composed announcement / newsletter sent to a filtered alumni audience."""

    subject = models.CharField(max_length=200)
    body_html = models.TextField(help_text="Rich-text body. Rendered into the email and the in-app notification preview.")
    audience = models.CharField(
        max_length=24,
        choices=BroadcastAudience.choices,
        default=BroadcastAudience.ALL_OPTED_IN,
    )
    audience_filter = models.JSONField(
        default=dict,
        blank=True,
        help_text="Free-form filter payload for non-trivial audiences (group_ids, country, year, programme).",
    )
    status = models.CharField(
        max_length=16,
        choices=BroadcastStatus.choices,
        default=BroadcastStatus.DRAFT,
        db_index=True,
    )
    created_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.PROTECT,
        related_name="alumni_broadcasts_authored",
    )
    scheduled_for = models.DateTimeField(null=True, blank=True)
    sent_at = models.DateTimeField(null=True, blank=True)
    sent_count = models.PositiveIntegerField(default=0)
    last_error = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    history = HistoricalRecords()

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["status", "scheduled_for"]),
        ]

    def __str__(self):
        return f"Broadcast<{self.pk} {self.status}: {self.subject[:48]}>"
