<?php
/**
 * stripe_pm_cleanup.php — Enforce a single active payment method per customer.
 *
 * Called when a customer adds a new card or payment method. Sets the new method
 * as the customer default, clears all subscription-level payment overrides so
 * they fall through to the customer default, then removes every other source or
 * payment method attached to the customer.
 *
 * Rationale: if a customer just added a new card, they almost certainly did so
 * to pay an outstanding or upcoming invoice. Leaving old cards in place risks
 * charging a card the customer intended to replace.
 *
 * Called from:
 *   stripe_event_card_c.php    — customer.source.created  (legacy card_/src_ added)
 *   stripe_event_payment_c.php — payment_method.attached  (modern pm_ added)
 *
 * NOT called on .updated events — updating existing card details does not
 * indicate intent to replace other payment methods.
 */

/**
 * Enforce single-payment-method policy for a customer.
 *
 * Order of operations:
 *   1. Set $KeepID as the customer-level billing default (so billing always has
 *      a valid target, even during the cleanup that follows).
 *   2. Clear default_payment_method / default_source overrides on every
 *      subscription so they all bill through the customer default.
 *   3. Detach all other pm_ payment methods.
 *   4. Delete all other legacy sources (card_, src_, bank account, etc.).
 *
 * Each sub-step catches its own exceptions so one failure does not abort the
 * rest of the cleanup.
 *
 * @param \Stripe\StripeClient $StripeClient  Authenticated Stripe client
 * @param string               $CustomerID    cus_xxx
 * @param string               $KeepID        ID of the payment method to keep
 *                                            (card_xxx, src_xxx, or pm_xxx)
 * @param object               $MyLogger      KLogger instance from the calling handler
 */
function DeleteOtherPaymentMethods(
    \Stripe\StripeClient $StripeClient,
    string $CustomerID,
    string $KeepID,
    object $MyLogger
): void {
    if ($CustomerID === '' || $KeepID === '') {
        $MyLogger->logDebug("DeleteOtherPaymentMethods: skipped — missing CustomerID or KeepID");
        return;
    }

    $MyLogger->logDebug("DeleteOtherPaymentMethods: start — CustomerID=$CustomerID KeepID=$KeepID");
    $Detached = 0;
    $Deleted  = 0;
    $Errors   = 0;

    // ── Step 1: Set new method as the customer-level billing default ──────────
    try {
        if (str_starts_with($KeepID, 'pm_')) {
            // Modern payment method — set via invoice_settings
            $StripeClient->customers->update($CustomerID, [
                'invoice_settings' => ['default_payment_method' => $KeepID],
            ]);
        } else {
            // Legacy card_ or src_ — set as default_source
            $StripeClient->customers->update($CustomerID, [
                'default_source' => $KeepID,
            ]);
        }
        $MyLogger->logDebug("DeleteOtherPaymentMethods: set customer default to $KeepID");
    } catch (\Exception $Ex) {
        $MyLogger->logError("DeleteOtherPaymentMethods: failed to set customer default — " . $Ex->getMessage());
        $Errors++;
    }

    // ── Step 2: Clear subscription-level payment overrides ────────────────────
    // A subscription's own default_payment_method or default_source overrides
    // the customer default. Clear them all so every subscription now routes
    // through the customer-level default we just set.
    try {
        $Subscriptions = $StripeClient->subscriptions->all([
            'customer' => $CustomerID,
            'status'   => 'all',
            'limit'    => 100,
        ]);
        foreach ($Subscriptions->autoPagingIterator() as $Sub) {
            $UpdateParams = [];
            if (!empty($Sub->default_payment_method)) {
                $UpdateParams['default_payment_method'] = '';
            }
            if (!empty($Sub->default_source)) {
                $UpdateParams['default_source'] = '';
            }
            if (!empty($UpdateParams)) {
                try {
                    $StripeClient->subscriptions->update($Sub->id, $UpdateParams);
                    $MyLogger->logDebug("DeleteOtherPaymentMethods: cleared payment override on subscription " . $Sub->id);
                } catch (\Exception $Ex) {
                    $MyLogger->logError("DeleteOtherPaymentMethods: failed to clear override on subscription " . $Sub->id . " — " . $Ex->getMessage());
                    $Errors++;
                }
            }
        }
    } catch (\Exception $Ex) {
        $MyLogger->logError("DeleteOtherPaymentMethods: failed to list subscriptions — " . $Ex->getMessage());
        $Errors++;
    }

    // ── Step 3: Detach all other pm_ payment methods ──────────────────────────
    // Listing without a type returns all attached payment methods regardless of
    // type (cards, bank accounts, etc.) — supported since Stripe API 2022-11-15.
    try {
        $PmList = $StripeClient->paymentMethods->all([
            'customer' => $CustomerID,
            'limit'    => 100,
        ]);
        foreach ($PmList->autoPagingIterator() as $Pm) {
            if ($Pm->id === $KeepID) continue;
            try {
                $StripeClient->paymentMethods->detach($Pm->id);
                $MyLogger->logDebug("DeleteOtherPaymentMethods: detached " . $Pm->id . " (type=" . ($Pm->type ?? '?') . ")");
                $Detached++;
            } catch (\Exception $Ex) {
                $MyLogger->logError("DeleteOtherPaymentMethods: failed to detach " . $Pm->id . " — " . $Ex->getMessage());
                $Errors++;
            }
        }
    } catch (\Exception $Ex) {
        $MyLogger->logError("DeleteOtherPaymentMethods: failed to list payment methods — " . $Ex->getMessage());
        $Errors++;
    }

    // ── Step 4: Delete all other legacy sources (card_, src_, bank accounts) ──
    try {
        $SourceList = $StripeClient->customers->allSources($CustomerID, ['limit' => 100]);
        foreach ($SourceList->autoPagingIterator() as $Source) {
            if ($Source->id === $KeepID) continue;
            try {
                $StripeClient->customers->deleteSource($CustomerID, $Source->id);
                $MyLogger->logDebug("DeleteOtherPaymentMethods: deleted source " . $Source->id . " (object=" . ($Source->object ?? '?') . ")");
                $Deleted++;
            } catch (\Exception $Ex) {
                $MyLogger->logError("DeleteOtherPaymentMethods: failed to delete source " . $Source->id . " — " . $Ex->getMessage());
                $Errors++;
            }
        }
    } catch (\Exception $Ex) {
        $MyLogger->logError("DeleteOtherPaymentMethods: failed to list sources — " . $Ex->getMessage());
        $Errors++;
    }

    $MyLogger->logDebug("DeleteOtherPaymentMethods: complete — Detached=$Detached Deleted=$Deleted Errors=$Errors CustomerID=$CustomerID");
}
