<?php

namespace Licenzo\Modules\EDD;

use Licenzo\Helper\Settings;

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

/**
 * Charges off-session Stripe PaymentIntents for subscription renewals via EDD Stripe.
 *
 * Invoked by SubscriptionRenewalService::processEddRenewal() on each billing cycle
 * via the licenzo_process_renewals cron event.
 *
 * @see EddStripeCompatibilityService — ensures setup_future_usage=off_session at checkout
 * @see \Licenzo\Services\SubscriptionRenewalService — the renewal orchestrator that calls chargeRenewal()
 */
class EddStripeRenewalPaymentService
{
    public function isAvailable(): bool
    {
        return (defined('EDD_STRIPE_VERSION') || class_exists('EDD_Stripe'))
            && function_exists('edds_api_request');
    }

    /**
     * Charge a Stripe PaymentIntent off-session for renewal.
     *
     * Uses edds_api_request() to create a PaymentIntent with the saved
     * customer and payment method from the original purchase.
     */
    public function chargeRenewal( string $stripeCustomerId, string $paymentMethodId, int $amountCents, string $currency, string $description = '', array $extraMetadata = []): array {
        if (!$this->isStripeAutoRenewEnabled()) {
            return [
                'success' => false,
                'mode'    => 'manual',
                'message' => 'Stripe auto renewal is disabled in Subscription Settings.',
            ];
        }

        if (!$this->isAvailable()) {
            return [
                'success' => false,
                'mode'    => 'manual',
                'message' => 'EDD Stripe gateway is unavailable.',
            ];
        }

        if ($stripeCustomerId === '' || $paymentMethodId === '') {
            return [
                'success' => false,
                'mode'    => 'manual',
                'message' => 'Missing Stripe customer or payment method for renewal.',
            ];
        }

        if ($amountCents <= 0) {
            return [
                'success' => false,
                'mode'    => 'manual',
                'message' => 'Invalid renewal amount.',
            ];
        }

        try {
            $metadata = array_merge([
                'licenzo_subscription' => '1',
                'payment_type'         => 'recurring',
            ], $extraMetadata);

            $intentArgs = [
                'amount'         => $amountCents,
                'currency'       => strtolower($currency),
                'customer'       => $stripeCustomerId,
                'payment_method' => $paymentMethodId,
                'off_session'    => true,
                'confirm'        => true,
                'metadata'       => $metadata,
            ];

            if ($description !== '') {
                $intentArgs['description'] = $description;
            }

            $intent = edds_api_request('PaymentIntent', 'create', $intentArgs);

            if (isset($intent->error)) {
                $message = is_object($intent->error) && isset($intent->error->message)
                    ? (string) $intent->error->message
                    : 'Unknown Stripe error';

                return [
                    'success' => false,
                    'mode'    => 'stripe',
                    'message' => $message,
                    'intent'  => $this->normalizeIntentSummary($intent),
                ];
            }

            $status = isset($intent->status) ? (string) $intent->status : '';

            if ($status === 'requires_action' || $status === 'requires_confirmation') {
                return [
                    'success' => false,
                    'mode'    => 'requires_action',
                    'message' => 'Payment requires customer authentication (3D Secure / SCA).',
                    'intent'  => $this->normalizeIntentSummary($intent),
                ];
            }

            if ($status !== 'succeeded') {
                return [
                    'success' => false,
                    'mode'    => 'stripe',
                    'message' => sprintf('Unexpected PaymentIntent status: %s', $status),
                    'intent'  => $this->normalizeIntentSummary($intent),
                ];
            }

            return [
                'success' => true,
                'mode'    => 'stripe',
                'message' => 'Renewal charge succeeded via EDD Stripe.',
                'intent'  => $this->normalizeIntentSummary($intent),
            ];
        } catch (\Throwable $e) {
            return [
                'success' => false,
                'mode'    => 'stripe',
                'message' => $e->getMessage(),
            ];
        }
    }

    private function normalizeIntentSummary($intent): ?array
    {
        if (!is_object($intent)) {
            return null;
        }

        $nextActionType = null;
        if (isset($intent->next_action) && is_object($intent->next_action)) {
            $nextActionType = isset($intent->next_action->type) ? (string) $intent->next_action->type : null;
        }

        return [
            'id'               => isset($intent->id) ? (string) $intent->id : null,
            'status'           => isset($intent->status) ? (string) $intent->status : null,
            'client_secret'    => isset($intent->client_secret) ? (string) $intent->client_secret : null,
            'next_action_type' => $nextActionType,
        ];
    }

    private function isStripeAutoRenewEnabled(): bool
    {
        $settings = Settings::getSubscriptionSettings();
        return (($settings['stripe_auto_renew'] ?? 'yes') === 'yes');
    }
}
