"""Comprehensive audit trail (PRD §5.1 FRFA-AM041, FRFA-CO030, FRSME-MEI022).

Every privileged write across RIMS / SME-Hub / MEL goes through
:func:`apps.core.audit.mixins.log_audit` (or the RIMS-specific shim
:func:`apps.rims.grants.audit_helper.audit_rims`) and lands in the
:class:`AuditLog` table.
"""
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import models


class AuditLog(models.Model):
    """PRD §5.1 FRFA-AM041 — comprehensive action log across application management."""

    class Action(models.TextChoices):
        CREATE = "CREATE", "Create"
        UPDATE = "UPDATE", "Update"
        DELETE = "DELETE", "Delete"
        ACCESS = "ACCESS", "Access"

    actor = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="audit_logs",
    )
    # Larger than the original 16 to accommodate domain-specific action codes
    # (e.g. FORCED_CLOSEOUT_APPROVED, DISBURSEMENT_BLOCKED_BY_CLOSEOUT) that
    # PRD audit trails require. The Action enum values remain valid; the
    # schema simply stops truncating longer codes silently at insert time.
    action = models.CharField(max_length=64, db_index=True)
    target_app = models.CharField(max_length=64, blank=True)
    target_model = models.CharField(max_length=64, blank=True, db_index=True)
    object_id = models.CharField(max_length=64, blank=True, db_index=True)
    object_repr = models.CharField(max_length=200, blank=True)
    changes = models.JSONField(null=True, blank=True)
    ip_address = models.GenericIPAddressField(null=True, blank=True)
    user_agent = models.CharField(max_length=512, blank=True)
    path = models.CharField(max_length=512, blank=True)
    method = models.CharField(max_length=8, blank=True)
    timestamp = models.DateTimeField(auto_now_add=True, db_index=True)

    class Meta:
        ordering = ["-timestamp"]
        indexes = [
            models.Index(fields=["actor", "timestamp"]),
            models.Index(fields=["target_model", "object_id"]),
        ]

    def save(self, *args, **kwargs):
        # M&E SRS Table 66 / PRD §5.1 — "Audit records shall not be modified or
        # deleted." An existing row cannot be re-saved; only inserts are allowed.
        if not self._state.adding:
            raise ValidationError("Audit log records are immutable and cannot be modified.")
        return super().save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        raise ValidationError("Audit log records are immutable and cannot be deleted.")
