<?php
namespace WalletUpPro\Core\Payments;

if (!defined('ABSPATH')) {
    exit;
}

/**
 * Single authority for "is this payment method enabled / configured / live at checkout".
 *
 * Three layers checked here, in order:
 *   A  "enabled"           — merchant toggled it on (wallet_up_enabled_methods)
 *   B  "configured"        — holder/phone filled in (wallet_up_transfer_call or mobile_money_settings)
 *   C  "liveAtCheckout"    — WC gateway per-method toggle is yes (woocommerce_wallet_up_settings.enable_<id>)
 *
 * Layer D (cart-level eligibility) is runtime-only and lives in the gateway's is_available() /
 * payment_fields() — it depends on the current cart and isn't cached here.
 *
 * Every UI that shows method counts, every save handler that gates method-level flags, and the
 * WC gateway's availability check should read from this resolver — NOT re-derive the sets.
 */
class MethodStatusResolver
{
    private const MOBILE_MONEY_IDS = [
        'mpesa_ke', 'orange_money_ci', 'mtn_momo_ci', 'mtn_momo_zm',
        'airtel_money_zm', 'moov_money_ci', 'wave_ci', 'zamtel_kwacha',
    ];

    /**
     * Full status snapshot: three sets of method IDs (enabled, configured, liveAtCheckout)
     * plus derived booleans per method. Pass a cache-busting flag only when you know options
     * just changed.
     *
     * @return array{
     *   enabled: string[],
     *   configured: string[],
     *   liveAtCheckout: string[],
     *   byMethod: array<string, array{enabled:bool, configured:bool, liveAtCheckout:bool, holder:string}>
     * }
     */
    public static function snapshot(): array
    {
        $enabledMap  = (array) get_option('wallet_up_enabled_methods', []);
        $transferCall = (array) get_option('wallet_up_transfer_call', []);
        $mobileMoney  = (array) get_option('wallet_up_mobile_money_settings', []);
        $gateway      = (array) get_option('woocommerce_wallet_up_settings', []);
        $gatewayOn    = !empty($gateway['enabled']) && $gateway['enabled'] === 'yes';

        $byMethod = [];
        $enabled = [];
        $configured = [];
        $liveAtCheckout = [];

        foreach ($enabledMap as $methodId => $isEnabled) {
            $methodId = (string) $methodId;
            $isEnabled = !empty($isEnabled) && $isEnabled !== 'false' && $isEnabled !== '0';

            $holder = self::resolveHolder($methodId, $transferCall, $mobileMoney);
            $isConfigured = $holder !== '';

            // Per-method WC toggle defaults to 'yes' when the key doesn't exist — matches
            // the gateway's form_fields default. Gateway master switch must also be on.
            $wcPerMethod = $gateway['enable_' . $methodId] ?? 'yes';
            $isLive = $gatewayOn && $isEnabled && $isConfigured && $wcPerMethod === 'yes';

            $byMethod[$methodId] = [
                'enabled'         => $isEnabled,
                'configured'      => $isConfigured,
                'liveAtCheckout'  => $isLive,
                'holder'          => $holder,
            ];

            if ($isEnabled)    { $enabled[] = $methodId; }
            if ($isEnabled && $isConfigured) { $configured[] = $methodId; }
            if ($isLive)       { $liveAtCheckout[] = $methodId; }
        }

        return [
            'enabled'        => $enabled,
            'configured'     => $configured,
            'liveAtCheckout' => $liveAtCheckout,
            'byMethod'       => $byMethod,
        ];
    }

    /**
     * Fast path: is a single method configured (has a holder on file)?
     * Equivalent to Layer B — used by save handlers to reject writes for unseeded methods.
     */
    public static function isConfigured(string $methodId): bool
    {
        return self::resolveHolder(
            $methodId,
            (array) get_option('wallet_up_transfer_call', []),
            (array) get_option('wallet_up_mobile_money_settings', [])
        ) !== '';
    }

    /**
     * Fast path: is a method enabled? (Layer A)
     */
    public static function isEnabled(string $methodId): bool
    {
        $enabled = (array) get_option('wallet_up_enabled_methods', []);
        $v = $enabled[$methodId] ?? false;
        return !empty($v) && $v !== 'false' && $v !== '0';
    }

    /**
     * Fast path: method passes A + B (i.e. can legitimately be sold to shoppers).
     * The WC gateway's is_available() uses this plus runtime cart checks.
     */
    public static function isReady(string $methodId): bool
    {
        return self::isEnabled($methodId) && self::isConfigured($methodId);
    }

    private static function resolveHolder(string $methodId, array $transferCall, array $mobileMoney): string
    {
        if (in_array($methodId, self::MOBILE_MONEY_IDS, true)) {
            return trim((string) ($mobileMoney[$methodId]['phone_number'] ?? ''));
        }
        return trim((string) ($transferCall[$methodId . '_holder'] ?? ''));
    }
}
