from __future__ import annotations

from django.conf import settings as django_settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from simorgh.core.models import TimeStampedModel, UUIDModel


class SettingScope(models.TextChoices):
    SYSTEM = "system", _("System")
    TENANT = "tenant", _("Tenant")
    ORG = "org", _("Organization Node")
    MODULE = "module", _("Module")
    USER = "user", _("User")


class SettingValue(UUIDModel, TimeStampedModel):
    """One row per (scope, scope_id, key) override.

    Resolution walks from the most specific scope down to the system default
    declared in `SettingDefinition`. `scope_id` is a free-form string so it
    can carry org-node ids, user ids, or module slugs without polymorphic FKs.
    """

    key = models.CharField(_("key"), max_length=128, db_index=True)
    scope = models.CharField(
        _("scope"),
        max_length=16,
        choices=SettingScope.choices,
        db_index=True,
    )
    scope_id = models.CharField(_("scope id"), max_length=128, blank=True, db_index=True)
    tenant = models.ForeignKey(
        "tenants.Tenant",
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="+",
    )
    value = models.JSONField(_("value"))
    updated_by = models.ForeignKey(
        django_settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
    )

    class Meta:
        verbose_name = _("setting value")
        verbose_name_plural = _("setting values")
        constraints = (
            models.UniqueConstraint(
                fields=("key", "scope", "scope_id", "tenant"),
                name="app_settings_value_unique",
            ),
        )
        indexes = (models.Index(fields=("tenant", "scope", "key")),)

    def __str__(self) -> str:
        return f"{self.key}@{self.scope}:{self.scope_id or '-'}"
