"""
Resolve store orders stuck at "Payment Initiated" because Safaricom's
callback never arrived. Each is checked with Daraja's STK Query: paid ones
are confirmed, the rest are marked failed and their stock released.

Paybill orders (no STK request) are left alone — staff confirm those.
Unanswered admin POS prompts (PosMpesaPayment) are settled the same way.

Run from cron every ~10 minutes, e.g. on cPanel:
    */10 * * * * cd /home/<user>/<app> && <venv>/bin/python manage.py expire_mpesa_payments
"""

from datetime import timedelta

from django.core.management.base import BaseCommand
from django.utils import timezone

from store.models import Order
from store.services import payment_service
from store.services.mpesa_service import MpesaError


class Command(BaseCommand):
    help = "Confirm or fail M-Pesa STK payments that have had no callback."

    def add_arguments(self, parser):
        parser.add_argument(
            "--minutes", type=int, default=10,
            help="Only check orders whose prompt was sent at least this long ago (default 10).",
        )

    def handle(self, *args, minutes, **options):
        cutoff = timezone.now() - timedelta(minutes=minutes)
        stale = (
            Order.objects
            .filter(status=Order.STATUS_PAYMENT_INITIATED, updated_at__lt=cutoff)
            .exclude(checkout_request_id="")
        )

        counts = {"paid": 0, "failed": 0, "error": 0}
        for order in stale:
            try:
                state = payment_service.query_and_apply(order, timeout_as_failed=True)
            except MpesaError as exc:
                counts["error"] += 1
                self.stderr.write(f"{order.order_reference}: {exc}")
                continue
            order.refresh_from_db()
            outcome = "paid" if order.status == Order.STATUS_PAID else "failed"
            counts[outcome] += 1
            self.stdout.write(f"{order.order_reference}: {state} -> {order.status}")

        self.stdout.write(self.style.SUCCESS(
            f"Checked {sum(counts.values())} order(s): "
            f"{counts['paid']} paid, {counts['failed']} failed, {counts['error']} could not be checked."
        ))

        # Admin POS prompts share the same Daraja account and callback.
        from inventory.models import PosMpesaPayment
        from inventory.services import pos_mpesa_service

        pos_counts = {"paid": 0, "failed": 0, "error": 0}
        stale_pos = (
            PosMpesaPayment.objects
            .filter(status=PosMpesaPayment.STATUS_PENDING, created_at__lt=cutoff)
            .exclude(checkout_request_id="")
        )
        for payment in stale_pos:
            state = pos_mpesa_service.refresh_status(payment, force=True, timeout_as_failed=True)
            payment.refresh_from_db()
            if state == "unknown":
                pos_counts["error"] += 1
                continue
            pos_counts["paid" if payment.status == PosMpesaPayment.STATUS_PAID else "failed"] += 1
            self.stdout.write(f"POS payment {payment.pk}: {state} -> {payment.status}")

        self.stdout.write(self.style.SUCCESS(
            f"Checked {sum(pos_counts.values())} POS prompt(s): "
            f"{pos_counts['paid']} paid, {pos_counts['failed']} failed, {pos_counts['error']} could not be checked."
        ))
