from __future__ import annotations

from django.conf import settings
from django.db import models
from django.utils.text import slugify

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


class GroupKind(models.TextChoices):
    COUNTRY = "country", "Country chapter"
    DISCIPLINE = "discipline", "Discipline"
    SECTOR = "sector", "Sector"
    COHORT = "cohort", "Cohort"


class NetworkGroup(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, unique=True)
    kind = models.CharField(max_length=16, choices=GroupKind.choices, default=GroupKind.DISCIPLINE)
    description = models.TextField(blank=True)
    banner_image = models.FileField(upload_to=upload_to_alumni_photos, blank=True, null=True)
    member_count = models.PositiveIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["title"]

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)[:255]
        super().save(*args, **kwargs)

    def __str__(self):
        return self.title


class GroupRole(models.TextChoices):
    MEMBER = "member", "Member"
    MODERATOR = "moderator", "Moderator"


class GroupMembership(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="alumni_group_memberships",
    )
    group = models.ForeignKey(
        NetworkGroup,
        on_delete=models.CASCADE,
        related_name="memberships",
    )
    role = models.CharField(max_length=16, choices=GroupRole.choices, default=GroupRole.MEMBER)
    joined_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=["user", "group"], name="uniq_group_membership"),
        ]


class EventVisibility(models.TextChoices):
    PUBLIC = "public", "Public"
    ALUMNI_ONLY = "alumni_only", "Alumni only"
    GROUP = "group", "Selected groups"


class EventStatus(models.TextChoices):
    """Moderation state — controls whether an event reaches the calendar.

    Events proposed by ordinary alumni start as PENDING and only become
    visible to others once an alumni officer (or admin) APPROVES them.
    Staff- and group-moderator-created events are auto-approved on save.
    """

    PENDING = "pending", "Pending approval"
    APPROVED = "approved", "Approved"
    REJECTED = "rejected", "Rejected"


class AlumniEvent(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, unique=True)
    description = models.TextField(blank=True)
    start_at = models.DateTimeField()
    end_at = models.DateTimeField()
    location = models.CharField(max_length=255, blank=True)
    virtual_url = models.URLField(blank=True)
    organiser = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="organised_alumni_events",
    )
    cover_image = models.FileField(upload_to=upload_to_alumni_photos, blank=True, null=True)
    capacity = models.PositiveIntegerField(default=0, help_text="0 means unlimited.")
    visibility = models.CharField(
        max_length=16,
        choices=EventVisibility.choices,
        default=EventVisibility.ALUMNI_ONLY,
    )
    groups = models.ManyToManyField(
        NetworkGroup,
        blank=True,
        related_name="events",
        help_text="Only used when visibility=GROUP.",
    )
    announced_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When the group-member announcement went out for this event.",
    )
    group_reminder_sent_at = models.DateTimeField(
        null=True,
        blank=True,
        help_text="When the 48h group-member nudge went out.",
    )
    status = models.CharField(
        max_length=16,
        choices=EventStatus.choices,
        default=EventStatus.APPROVED,
        db_index=True,
        help_text=(
            "Moderation state — only APPROVED events appear on the calendar. "
            "Events are APPROVED by default (staff/importers/seeders); the alumni "
            "proposal flow explicitly downgrades a non-approver's event to PENDING."
        ),
    )
    reviewed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="reviewed_alumni_events",
        help_text="The officer/admin who approved or rejected this event.",
    )
    reviewed_at = models.DateTimeField(null=True, blank=True)
    review_notes = models.TextField(
        blank=True,
        help_text="Officer feedback shown to the organiser, e.g. why an event was rejected.",
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-start_at"]

    def save(self, *args, **kwargs):
        if not self.slug:
            base = slugify(self.title)[:240] or "alumni-event"
            candidate = base
            n = 2
            while AlumniEvent.objects.filter(slug=candidate).exclude(pk=self.pk).exists():
                candidate = f"{base}-{n}"
                n += 1
            self.slug = candidate
        super().save(*args, **kwargs)

    def __str__(self):
        return self.title


class EventRegistration(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="alumni_event_registrations",
    )
    event = models.ForeignKey(
        AlumniEvent,
        on_delete=models.CASCADE,
        related_name="registrations",
    )
    registered_at = models.DateTimeField(auto_now_add=True)
    reminder_sent_at = models.DateTimeField(null=True, blank=True)
    attended = models.BooleanField(default=False)
    feedback_rating = models.PositiveSmallIntegerField(null=True, blank=True)
    feedback_text = models.TextField(blank=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=["user", "event"], name="uniq_event_registration"),
        ]


class MentorshipStatus(models.TextChoices):
    REQUESTED = "requested", "Requested"
    ACTIVE = "active", "Active"
    COMPLETED = "completed", "Completed"
    CANCELLED = "cancelled", "Cancelled"
    DECLINED = "declined", "Declined"


class MentorshipCadence(models.TextChoices):
    WEEKLY = "weekly", "Weekly"
    BIWEEKLY = "biweekly", "Every two weeks"
    MONTHLY = "monthly", "Monthly"
    AS_NEEDED = "as_needed", "As needed"


class MentorshipPairing(models.Model):
    mentor = models.ForeignKey(
        AlumniProfile,
        on_delete=models.CASCADE,
        related_name="mentorships_as_mentor",
    )
    mentee = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="mentorships_as_mentee",
    )
    status = models.CharField(
        max_length=16,
        choices=MentorshipStatus.choices,
        default=MentorshipStatus.REQUESTED,
    )
    topic = models.CharField(max_length=255, blank=True)
    goals = models.TextField(
        blank=True,
        help_text="What the mentee wants out of this relationship — set at request time.",
    )
    cadence = models.CharField(
        max_length=16,
        choices=MentorshipCadence.choices,
        default=MentorshipCadence.MONTHLY,
    )
    duration_months = models.PositiveSmallIntegerField(
        null=True,
        blank=True,
        help_text="Planned duration in months. Informational; doesn't auto-close the pairing.",
    )
    match_score = models.FloatField(default=0.0)
    started_at = models.DateTimeField(null=True, blank=True)
    ended_at = models.DateTimeField(null=True, blank=True)
    notes = models.TextField(blank=True)
    outcome = models.TextField(
        blank=True,
        help_text="Summary captured when the pairing is completed.",
    )
    outcome_rating = models.PositiveSmallIntegerField(
        null=True,
        blank=True,
        help_text="Mentee-reported impact 1–5 at completion.",
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["mentor", "mentee", "topic"],
                name="uniq_pairing_per_mentor_mentee_topic",
            ),
        ]
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.mentor_id} ↔ {self.mentee_id} ({self.status})"


class MentorshipNote(models.Model):
    pairing = models.ForeignKey(
        MentorshipPairing,
        on_delete=models.CASCADE,
        related_name="session_notes",
    )
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="alumni_mentorship_notes",
    )
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]


class GroupAnnouncement(models.Model):
    """A message posted by a group moderator to all members of the group."""

    group = models.ForeignKey(
        NetworkGroup,
        on_delete=models.CASCADE,
        related_name="announcements",
    )
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="alumni_group_announcements",
    )
    title = models.CharField(max_length=200)
    body = models.TextField(help_text="Rich-text announcement body.")
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]

    def __str__(self):
        return f"{self.group.slug} · {self.title[:48]}"


class LeadershipRequestStatus(models.TextChoices):
    PENDING = "pending", "Pending"
    APPROVED = "approved", "Approved"
    DECLINED = "declined", "Declined"


class ChapterLeadershipRequest(models.Model):
    """A member's request to be made a leader (moderator) of a chapter/group.

    An alumni officer reviews the request; approval promotes the member to
    moderator of the group via ``set_member_role``.
    """

    group = models.ForeignKey(
        NetworkGroup,
        on_delete=models.CASCADE,
        related_name="leadership_requests",
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="chapter_leadership_requests",
    )
    message = models.TextField(
        blank=True,
        help_text="Optional note from the member on why they'd like to lead.",
    )
    status = models.CharField(
        max_length=16,
        choices=LeadershipRequestStatus.choices,
        default=LeadershipRequestStatus.PENDING,
        db_index=True,
    )
    reviewed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="reviewed_leadership_requests",
    )
    reviewed_at = models.DateTimeField(null=True, blank=True)
    review_notes = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        ordering = ["-created_at"]
        constraints = [
            models.UniqueConstraint(
                fields=["group", "user"],
                condition=models.Q(status="pending"),
                name="uniq_pending_leadership_request",
            )
        ]

    def __str__(self):
        return f"{self.user_id} → lead {self.group.slug} ({self.status})"
