"""
inventory/signals.py
─────────────────────
Auto-create an inventory Sale when a store Order transitions to PAID.
"""

import logging

from django.db.models.signals import post_save
from django.dispatch import receiver

from store.models import Order

logger = logging.getLogger(__name__)

# Store previous status across pre_save / post_save
_prev_status: dict[int, str] = {}


@receiver(post_save, sender=Order)
def handle_paid_order(sender, instance: Order, created: bool, **kwargs):
    """When an Order becomes PAID, mirror it as an inventory Sale."""
    if created:
        return

    prev = _prev_status.pop(instance.pk, None)
    if prev == instance.status:
        return  # no change

    if instance.status == Order.STATUS_PAID:
        try:
            from inventory.services.sales_service import create_sale_from_order
            sale = create_sale_from_order(instance)
            if sale:
                logger.info(
                    "Inventory sale auto-created: %s ← order %s",
                    sale.invoice_number, instance.order_reference,
                )
        except Exception as exc:
            # Never let inventory errors break the order flow — but make it
            # visible: a paid order with no inventory sale skews stock & reports.
            from system_logs.models import SystemLog
            from system_logs.services import log_event

            log_event(
                SystemLog.MODULE_SALES, "order.inventory_sale.failed",
                f"Paid order {instance.order_reference} could not be recorded as an inventory sale: {exc}. "
                "Stock and sales reports are missing it — record the sale manually once the cause is fixed.",
                level=SystemLog.LEVEL_ERROR, reference=instance.order_reference,
                phone_number=instance.phone_number, mpesa_receipt=instance.mpesa_receipt_number,
                related=instance, exc=exc, alert=True,
            )


from django.db.models.signals import pre_save


@receiver(pre_save, sender=Order)
def cache_order_status(sender, instance: Order, **kwargs):
    if instance.pk:
        try:
            _prev_status[instance.pk] = Order.objects.values_list("status", flat=True).get(pk=instance.pk)
        except Order.DoesNotExist:
            pass
