<?php
/**
 * BookiFlex Payment Extension
 *
 * @package    BookiFlex
 * @subpackage Payment
 * @author     BookiFlex
 * @copyright  Copyright (c) 2025 BookiFlex
 * @license    GPL-2.0-or-later
 *
 * @link       https://bookiflex.com
 */


declare(strict_types=1);
namespace BookiFlex\Extensions\Payment\Service;

use BookiFlex\Core\Contract\Payment\PaymentGatewayManagerInterface;
use BookiFlex\Extensions\Payment\Infrastructure\Payum\PayumBuilder;
use BookiFlex\Extensions\Payment\Model\Payment;
use Payum\Core\Bridge\PlainPhp\Security\TokenFactory;
use Payum\Core\Payum;
use Payum\Core\Storage\StorageInterface;

defined( 'ABSPATH' ) || exit;

class PaymentGatewayManager implements PaymentGatewayManagerInterface
{
    private array $paymentGateways = [];

    /**
     * Register a payment gateway.
     *
     * Payum-backed gateways pass both factories. Omitting them registers an
     * external gateway (e.g. WooCommerce): a null gatewayFactory marks the entry
     * as external — it is listed for the admin (see getPaymentGateways()) but
     * skipped by makePayum().
     *
     * @param string $id payment gateway factory identifier
     * @param string $name name of the payment gateway
     * @param bool $supportAuthorize gateway supports authorization payment
     * @param callable|null $gatewayFactory
     * @param callable|null $gatewaySettingsFactory settings for the payment gateway
     * @param callable|null $adminSettingsFactory
     */
    public function registerPaymentGateway(
        string $id,
        string $name,
        bool $supportAuthorize,
        ?callable $gatewayFactory = null,
        ?callable $gatewaySettingsFactory = null,
        ?callable $adminSettingsFactory = null
    ): void {
        $this->paymentGateways[$id] = [
            'id'                     => $id,
            'name'                   => $name,
            'supportAuthorize'       => $supportAuthorize,
            'gatewayFactory'         => $gatewayFactory,
            'gatewaySettingsFactory' => $gatewaySettingsFactory,
            'adminSettingsFactory'   => $adminSettingsFactory,
        ];
    }

    public function getPaymentGateways(): array
    {
        return $this->paymentGateways;
    }

    public function makePayum(StorageInterface $storage, StorageInterface $tokenStorage): Payum
    {
        $builder = (new PayumBuilder())
            ->addStorage(
                Payment::class,
                $storage
            )
            ->setTokenStorage($tokenStorage)
            ->setTokenFactory(function ($tokenStorage, $storageRegistry) {
                return new TokenFactory($tokenStorage, $storageRegistry);
            })
            ->setGenericTokenFactoryPaths([
                'capture'   => rest_url('bflex/v1/payment/capture'),
                'authorize' => rest_url('bflex/v1/payment/authorize'),
                'notify'    => rest_url('bflex/v1/payment/notify'),
                'cancel'    => rest_url('bflex/v1/payment/cancel'),
            ]);

        foreach ($this->paymentGateways as $gateway) {
            // External gateways (e.g. WooCommerce) are not backed by Payum.
            if ($gateway['gatewayFactory'] === null) {
                continue;
            }

            $builder
                ->addGatewayFactory($gateway['id'], $gateway['gatewayFactory'])
                ->addGateway($gateway['id'], $gateway['gatewaySettingsFactory']());
        }

        return $builder->getPayum();
    }
}
