from __future__ import annotations

from django.conf import settings
from django.db import models
from django.utils.translation import gettext_lazy as _

from simorgh.core.models import TimeStampedModel, UUIDModel


class AuditLog(UUIDModel, TimeStampedModel):
    """Append-only record of an auditable event.

    Not a `TenantScopedModel` because some events are tenant-less (system,
    pre-resolution failures, superuser actions across tenants). Tenant +
    org_node are nullable FKs instead.
    """

    tenant = models.ForeignKey(
        "tenants.Tenant",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
    )
    organization_node = models.ForeignKey(
        "organizations.OrganizationNode",
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
    )
    actor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name="+",
    )
    action = models.CharField(_("action"), max_length=128, db_index=True)
    resource_type = models.CharField(_("resource type"), max_length=128, db_index=True)
    resource_id = models.CharField(_("resource id"), max_length=64, db_index=True, blank=True)
    before = models.JSONField(_("before"), null=True, blank=True)
    after = models.JSONField(_("after"), null=True, blank=True)
    ip_address = models.GenericIPAddressField(_("IP"), null=True, blank=True)
    user_agent = models.CharField(_("user agent"), max_length=256, blank=True)
    extra = models.JSONField(_("extra"), default=dict, blank=True)

    class Meta:
        verbose_name = _("audit log")
        verbose_name_plural = _("audit logs")
        ordering = ("-created_at",)
        indexes = (
            models.Index(fields=("tenant", "resource_type", "resource_id")),
            models.Index(fields=("tenant", "actor", "-created_at")),
            models.Index(fields=("tenant", "action", "-created_at")),
        )

    def __str__(self) -> str:
        return f"{self.action} {self.resource_type}#{self.resource_id}"
