from __future__ import annotations

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


class Module(models.Model):
    """A platform capability. Rows are mirrored from the code registry (sync_registry)."""

    class Status(models.TextChoices):
        AVAILABLE = "available", "Available"
        PLANNED = "planned", "Planned"
        DEPRECATED = "deprecated", "Deprecated"

    code = models.CharField(max_length=50, primary_key=True)
    title_fa = models.CharField(max_length=120)
    description_fa = models.TextField(blank=True, default="")
    status = models.CharField(max_length=12, choices=Status.choices, default=Status.AVAILABLE)
    is_core = models.BooleanField(default=False)
    sort_order = models.PositiveSmallIntegerField(default=0)

    class Meta:
        db_table = "modules"
        ordering = ["sort_order", "code"]

    def __str__(self):
        return self.code


class ModuleDependency(models.Model):
    module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name="dependencies")
    depends_on = models.ForeignKey(Module, on_delete=models.CASCADE, related_name="dependents")

    class Meta:
        db_table = "module_dependencies"
        constraints = [
            models.UniqueConstraint(fields=["module", "depends_on"], name="unique_module_dependency"),
            models.CheckConstraint(
                condition=~models.Q(module=models.F("depends_on")), name="module_not_self_dependent"
            ),
        ]


class OrganizationModule(models.Model):
    """Per-organization enablement. Disabling never deletes the module's data."""

    organization = models.ForeignKey(
        "organizations.Organization", on_delete=models.CASCADE, related_name="module_states"
    )
    module = models.ForeignKey(Module, on_delete=models.PROTECT, related_name="organization_states")
    is_enabled = models.BooleanField(default=False)
    enabled_at = models.DateTimeField(null=True, blank=True)
    disabled_at = models.DateTimeField(null=True, blank=True)
    changed_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="+"
    )

    class Meta:
        db_table = "organization_modules"
        constraints = [
            models.UniqueConstraint(fields=["organization", "module"], name="unique_organization_module")
        ]


class ModuleRequest(models.Model):
    """An organization manager asking NoTeam to enable a module; only the super admin can decide."""

    class Status(models.TextChoices):
        PENDING = "pending", "Pending"
        APPROVED = "approved", "Approved"
        REJECTED = "rejected", "Rejected"

    organization = models.ForeignKey(
        "organizations.Organization", on_delete=models.CASCADE, related_name="module_requests"
    )
    module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name="requests")
    requested_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="+"
    )
    status = models.CharField(max_length=10, choices=Status.choices, default=Status.PENDING)
    note = models.CharField(max_length=500, blank=True, default="")  # reason given when rejecting
    decided_by = models.ForeignKey(
        settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="+"
    )
    decided_at = models.DateTimeField(null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "module_requests"
        ordering = ["-created_at", "-id"]
        constraints = [
            models.UniqueConstraint(
                fields=["organization", "module"],
                condition=models.Q(status="pending"),
                name="one_pending_request_per_module",
            )
        ]
