<?php

namespace Licenzo\Modules\EDD;

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

/**
 * Gateway eligibility policy for Licenzo's EDD integration on v1.1.0.
 *
 * Licenzo's scheduled renewal path for EDD is Stripe-only: it calls
 * `edds_api_request('PaymentIntent', 'create', ...)` against the saved
 * Stripe payment method on the subscription's Stripe Customer. No other
 * EDD gateway (PayPal, Amazon, manual, 2Checkout, etc.) exposes the
 * PaymentMethod-reuse primitive that this path depends on.
 *
 * Consequences if a non-Stripe EDD order were silently scheduled for
 * Licenzo-driven renewal:
 *  - Renewal cron fires on the due date.
 *  - SubscriptionRenewalService::processEddRenewal() cannot resolve a
 *    Stripe PaymentMethod (there is none) and fails the schedule.
 *  - Subscription slides into dunning despite the customer's initial
 *    purchase being fully paid.
 *  - Customer never gets a renewal invoice from the correct gateway;
 *    their subscription silently expires.
 *
 * Policy decision (v1.1.0): we do NOT attempt to masquerade as a
 * renewal orchestrator for non-Stripe gateways. Instead:
 *  - New purchases on a non-Stripe gateway create the subscription and
 *    license as usual (the customer paid — entitlement is owed).
 *  - No renewal schedule is written. `recurring_amount` is forced to 0
 *    to reflect the single-cycle nature of the billing.
 *  - A per-order note is added on the EDD order so the admin sees why.
 *  - A `subscription_created_single_cycle` event is logged with the
 *    offending gateway slug.
 *  - An admin notice aggregates recent single-cycle creations so the
 *    operator can plan outreach before expiry.
 *
 * Operators who have a non-core EDD gateway that does support PaymentMethod
 * reuse can opt additional gateways into recurring eligibility via the
 * `licenzo_edd_recurring_eligible_gateways` filter. The default list
 * (`stripe`) covers the official EDD Stripe gateway slug and anything
 * containing `stripe` is treated as a Stripe variant (e.g. `stripe_ach`,
 * `stripe_sepa`, or the legacy `edd_stripe` slug some installs carry).
 */
class EddGatewayPolicy
{
    public const ELIGIBLE_FILTER = 'licenzo_edd_recurring_eligible_gateways';

    public const EVENT_SINGLE_CYCLE = 'subscription_created_single_cycle';

    /**
     * Default gateway slugs we know can drive Licenzo renewals.
     * Anything whose slug contains one of these tokens is also treated
     * as eligible (covers `stripe`, `stripe_ach`, `edd_stripe`, etc.).
     */
    public const DEFAULT_ELIGIBLE = ['stripe'];

    /**
     * Returns true when the supplied EDD gateway slug is safe to schedule
     * Licenzo-driven recurring renewals against.
     */
    public static function isRecurringEligible(string $gateway): bool
    {
        $normalized = strtolower(trim($gateway));
        if ($normalized === '') {
            return false;
        }

        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound -- Constant resolves to 'licenzo_edd_recurring_eligible_gateways'.
        $eligible = (array) apply_filters(static::ELIGIBLE_FILTER, static::DEFAULT_ELIGIBLE);
        $eligible = array_filter(array_map(static function ($slug) {
            return strtolower(trim((string) $slug));
        }, $eligible));

        if (in_array($normalized, $eligible, true)) {
            return true;
        }

        foreach ($eligible as $token) {
            if ($token !== '' && strpos($normalized, $token) !== false) {
                return true;
            }
        }

        return false;
    }

    /**
     * Returns the normalized (trimmed + lowercased) gateway slug for
     * logging / comparison. Preserves the original casing only when it
     * is the empty string (so callers can still branch on "unknown").
     */
    public static function normalizeSlug(string $gateway): string
    {
        return strtolower(trim($gateway));
    }
}
