from __future__ import annotations

from django.conf import settings
from django.db import models
from django.db.models import Q


class Organization(models.Model):
    """A tenant. Exactly one row has kind=platform: NoTeam's own staff organization."""

    class Kind(models.TextChoices):
        PLATFORM = "platform", "Platform"
        CUSTOMER = "customer", "Customer"

    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=64, unique=True, allow_unicode=False)
    kind = models.CharField(max_length=10, choices=Kind.choices, default=Kind.CUSTOMER)
    is_active = models.BooleanField(default=True)
    # dashboard colour chosen by the organization's manager; applies to every member (see ACCENT_COLORS)
    accent_color = models.CharField(max_length=20, default="violet")
    logo = models.FileField(upload_to="org-logos/", null=True, blank=True)  # png/jpeg/webp, checked on upload
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "organizations"
        ordering = ["id"]
        constraints = [
            models.UniqueConstraint(
                fields=["kind"], condition=Q(kind="platform"), name="single_platform_organization"
            )
        ]

    def __str__(self):
        return self.name

    @property
    def is_platform(self) -> bool:
        return self.kind == self.Kind.PLATFORM


class OrganizationMembership(models.Model):
    """A user's membership in one organization. One login can have many memberships."""

    class Status(models.TextChoices):
        ACTIVE = "active", "Active"
        SUSPENDED = "suspended", "Suspended"
        LEFT = "left", "Left"

    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="memberships")
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="memberships")
    personnel_code = models.CharField(max_length=50, null=True, blank=True)
    status = models.CharField(max_length=10, choices=Status.choices, default=Status.ACTIVE)
    joined_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "organization_memberships"
        constraints = [
            models.UniqueConstraint(fields=["user", "organization"], name="unique_user_organization"),
            models.UniqueConstraint(
                fields=["organization", "personnel_code"],
                condition=Q(personnel_code__isnull=False),
                name="unique_personnel_code_per_organization",
            ),
        ]

    def __str__(self):
        return f"{self.user_id}@{self.organization_id}"

    @property
    def is_active(self) -> bool:
        return self.status == self.Status.ACTIVE


class OrganizationAssignment(models.Model):
    """Customer organizations a platform-staff membership is responsible for
    (data scope `assigned_organizations`)."""

    membership = models.ForeignKey(
        OrganizationMembership, on_delete=models.CASCADE, related_name="assignments"
    )
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE, related_name="assigned_staff")

    class Meta:
        db_table = "organization_assignments"
        constraints = [
            models.UniqueConstraint(fields=["membership", "organization"], name="unique_assignment")
        ]
