"""
system_logs/models.py
──────────────────────
One log for every module: payment traffic (what we sent to Safaricom and what
came back), failures in business processes, and unexpected errors. Written
via system_logs.services.log_event() on its own database connection
(see routers.py) so entries survive when the failing operation rolls back.

Successful business actions (a sale, a stock movement) are still audited in
inventory.AuditLog — this log is for integrations and things going wrong.
"""

from django.conf import settings
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.utils import timezone


class SystemLog(models.Model):
    LEVEL_INFO    = "info"
    LEVEL_WARNING = "warning"
    LEVEL_ERROR   = "error"
    LEVELS = [
        (LEVEL_INFO,    "Info"),
        (LEVEL_WARNING, "Warning"),
        (LEVEL_ERROR,   "Error"),
    ]

    MODULE_PAYMENTS  = "payments"
    MODULE_STORE     = "store"
    MODULE_POS       = "pos"
    MODULE_SALES     = "sales"
    MODULE_INVENTORY = "inventory"
    MODULE_PAYOUTS   = "payouts"
    MODULE_EXPENSES  = "expenses"
    MODULE_CATALOG   = "catalog"
    MODULE_SYSTEM    = "system"
    MODULES = [
        (MODULE_PAYMENTS,  "Payments (M-Pesa)"),
        (MODULE_STORE,     "Online store"),
        (MODULE_POS,       "POS"),
        (MODULE_SALES,     "Sales"),
        (MODULE_INVENTORY, "Inventory"),
        (MODULE_PAYOUTS,   "Author payouts"),
        (MODULE_EXPENSES,  "Expenses"),
        (MODULE_CATALOG,   "Catalog"),
        (MODULE_SYSTEM,    "System"),
    ]

    created_at  = models.DateTimeField(default=timezone.now, db_index=True)
    level       = models.CharField(max_length=10, choices=LEVELS, db_index=True)
    module      = models.CharField(max_length=20, choices=MODULES, db_index=True)
    event       = models.CharField(
        max_length=80, db_index=True,
        help_text="Machine-readable event code, e.g. mpesa.callback.unmatched",
    )
    message     = models.TextField()

    # Searchable references — fill whichever apply.
    reference           = models.CharField(
        max_length=100, blank=True, db_index=True,
        help_text="Order reference, invoice number, POS payment id, …",
    )
    checkout_request_id = models.CharField(max_length=100, blank=True, db_index=True)
    phone_number        = models.CharField(max_length=20, blank=True, db_index=True)
    mpesa_receipt       = models.CharField(max_length=50, blank=True, db_index=True)
    related_model       = models.CharField(max_length=100, blank=True, help_text="app_label.model")
    related_id          = models.CharField(max_length=50, blank=True)

    # What we sent and what came back (secrets stripped), and the error.
    http_status   = models.PositiveSmallIntegerField(null=True, blank=True)
    request_data  = models.JSONField(null=True, blank=True, encoder=DjangoJSONEncoder)
    response_data = models.JSONField(null=True, blank=True, encoder=DjangoJSONEncoder)
    traceback     = models.TextField(blank=True)

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.SET_NULL,
        null=True, blank=True, related_name="+",
        help_text="Staff member whose action triggered this, if any.",
    )

    alert_sent_at    = models.DateTimeField(null=True, blank=True)
    resolved         = models.BooleanField(default=False, db_index=True)
    resolved_by      = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.SET_NULL,
        null=True, blank=True, related_name="+",
    )
    resolved_at      = models.DateTimeField(null=True, blank=True)
    resolution_notes = models.TextField(blank=True)

    class Meta:
        ordering = ["-created_at"]
        verbose_name = "System Log entry"
        verbose_name_plural = "System Log"
        indexes = [
            models.Index(fields=["level", "resolved", "created_at"]),
            models.Index(fields=["module", "created_at"]),
        ]

    def __str__(self) -> str:
        return f"[{self.level.upper()}] {self.module} · {self.event} · {self.created_at:%Y-%m-%d %H:%M}"
