# payments/views_refund.py  (new or move from views.py)
import logging
from decimal import Decimal
from django.db import transaction
from django.utils.timezone import now

from payments.models import (
    RechargePaymentSummary,
    ViralPeWallet, ViralPeWalletUsage,
)

LOG = logging.getLogger(__name__)

TWOPL = Decimal("0.01")
def _D(x) -> Decimal:
    return Decimal(str(x or "0")).quantize(TWOPL)

@transaction.atomic
def process_recharge_refund(summary: RechargePaymentSummary) -> dict:
    """
    Idempotent refund: credits all components (external, internal, gateway)
    into ViralPe Wallet. Safe to call multiple times.
    Returns a dict with credited amounts for auditing.
    """
    # Lock the row to serialize concurrent attempts
    summary = RechargePaymentSummary.objects.select_for_update().get(pk=summary.pk)

    status = (summary.recharge_status or "").strip().lower()
    if summary.is_refunded or status not in {"failure", "error"}:
        return {"ok": True, "idempotent": True, "credited": "0.00"}

    user     = summary.user
    order_id = summary.order_id

    ext_amt = _D(summary.used_external_wallet)
    int_amt = _D(summary.used_internal_wallet)
    gw_amt  = _D(summary.paid_via_gateway)

    vp_wallet, _ = ViralPeWallet.objects.select_for_update().get_or_create(user=user)

    credited = Decimal("0.00")

    def credit_once(purpose: str, amount: Decimal):
        nonlocal credited, vp_wallet
        if amount <= 0:
            return
        
        note = (summary.status_message or "")[:500]  # trim if your column is short

        # Ledger idempotency — one line per (user, order_id, purpose_code, purpose)
        line, created = ViralPeWalletUsage.objects.get_or_create(
            user=user,
            order_id=order_id,
            transaction_type="credit",
            purpose_code="payment_auto_refund",
            purpose=purpose,
            # defaults={"amount_used": amount, "purpose_note": summary.status_message},
            defaults={"amount_used": amount, "purpose_note": note},

        )
        if created:
            vp_wallet.balance = _D(vp_wallet.balance) + amount
            vp_wallet.save(update_fields=["balance"])
            credited += amount

    # credit_once(f"Refund (Ext→VP) - {order_id}", ext_amt)
    # credit_once(f"Refund (VP→VP) - {order_id}",  int_amt)
    # credit_once(f"Refund (PG→VP) - {order_id}",  gw_amt)
    
    credit_once(f"Refund (Ext->VP) - {order_id}", ext_amt)
    credit_once(f"Refund (VP->VP) - {order_id}",  int_amt)
    credit_once(f"Refund (PG->VP) - {order_id}",  gw_amt)

    # Mark summary as refunded (and keep a human reason)
    summary.is_refunded   = True
    summary.refunded_on   = now()
    summary.refund_reason = summary.refund_reason or "Recharge Failed"
    summary.save(update_fields=["is_refunded", "refunded_on", "refund_reason"])

    return {"ok": True, "credited": f"{credited:.2f}", "breakdown": {
        "external": f"{ext_amt:.2f}", "internal": f"{int_amt:.2f}", "gateway": f"{gw_amt:.2f}"
    }}




@transaction.atomic
def process_recharge_refund_new(summary: RechargePaymentSummary, *, force_fail: bool=False) -> dict:
    """
    Idempotent refund: credits all components (external, internal, gateway)
    into ViralPe Wallet. Safe to call multiple times.

    If `force_fail` is True, treat pending as failure (for coerced provider FAIL/ERROR).
    """
    # Lock the row to serialize concurrent attempts
    summary = RechargePaymentSummary.objects.select_for_update().get(pk=summary.pk)

    status = (summary.recharge_status or "").strip().lower()
    failed_like = {"failure", "error"}
    if force_fail and status in {"pending", "queued", "initiated", ""}:
        status = "failure"  # local override to allow refund path

    if summary.is_refunded or status not in failed_like:
        return {"ok": True, "idempotent": True, "credited": "0.00"}

    user     = summary.user
    order_id = summary.order_id

    ext_amt = _D(summary.used_external_wallet)
    int_amt = _D(summary.used_internal_wallet)
    gw_amt  = _D(summary.paid_via_gateway)

    vp_wallet, _ = ViralPeWallet.objects.select_for_update().get_or_create(user=user)

    credited = Decimal("0.00")

    def credit_once(purpose: str, amount: Decimal):
        nonlocal credited, vp_wallet
        if amount <= 0:
            return
        note = (summary.status_message or "")[:500]

        # Ledger idempotency — one line per (user, order_id, purpose_code, purpose)
        line, created = ViralPeWalletUsage.objects.get_or_create(
            user=user,
            order_id=order_id,
            transaction_type="credit",
            purpose_code="payment_auto_refund",
            purpose=purpose,
            defaults={"amount_used": amount, "purpose_note": note},
        )
        if created:
            vp_wallet.balance = _D(vp_wallet.balance) + amount
            vp_wallet.save(update_fields=["balance"])
            credited += amount

    credit_once(f"Refund (Ext->VP) - {order_id}", ext_amt)
    credit_once(f"Refund (VP->VP) - {order_id}",  int_amt)
    credit_once(f"Refund (PG->VP) - {order_id}",  gw_amt)

    # Mark summary as refunded (and keep a human reason)
    summary.is_refunded   = True
    summary.refunded_on   = now()
    summary.refund_reason = summary.refund_reason or "Recharge Failed"
    summary.save(update_fields=["is_refunded", "refunded_on", "refund_reason"])

    return {"ok": True, "credited": f"{credited:.2f}", "breakdown": {
        "external": f"{ext_amt:.2f}", "internal": f"{int_amt:.2f}", "gateway": f"{gw_amt:.2f}"
    }}
