<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase, WordPress.Files.FileName.InvalidClassFileName
/**
 * Payment Gateway Registry
 *
 * @package Autoship Cloud
 * @since 2.11.0
 */

namespace Autoship\Modules\Payments\Services;

use Autoship\Domain\AbstractPaymentGateway;
use Autoship\Domain\PaymentIntegrationFactory;
use Autoship\Services\Logging\Logger;
use Exception;

/**
 * Registry service for managing payment gateways.
 *
 * @package Autoship\Modules\PaymentGateways\Services
 * @since 3.0.0
 */
class PaymentGatewayRegistry {

	/**
	 * Registered gateways.
	 *
	 * @var array
	 */
	private array $gateways = array();

	/**
	 * The payment method type registry.
	 *
	 * @var PaymentMethodTypeRegistry
	 */
	private PaymentMethodTypeRegistry $type_registry;

	/**
	 * Constructor.
	 *
	 * @param PaymentMethodTypeRegistry $type_registry The type registry instance.
	 */
	public function __construct( PaymentMethodTypeRegistry $type_registry ) {
		$this->type_registry = $type_registry;
	}

	/**
	 * Initialize the registry with available gateways.
	 *
	 * Uses payment_gateways() instead of get_available_payment_gateways() to
	 * avoid firing each gateway's is_available() and the
	 * woocommerce_available_payment_gateways filter chain during init. That
	 * cascade can trigger WC()->cart->calculate_totals() side effects which,
	 * with autoship items in cart, interfere with session-stored notices
	 * (e.g. the "Coupon X was removed" message from a prior request).
	 *
	 * @return void
	 */
	public function initialize(): void {
		$all_gateways       = WC()->payment_gateways()->payment_gateways();
		$available_gateways = array_filter(
			$all_gateways,
			static function ( $gateway ) {
				return isset( $gateway->enabled ) && 'yes' === $gateway->enabled;
			}
		);
		$supported_methods  = $this->type_registry->get_valid_methods();

		foreach ( $available_gateways as $gateway_id => $gateway ) {
			if ( array_key_exists( $gateway_id, $supported_methods ) ) {
				try {
					$integration = PaymentIntegrationFactory::create( $gateway_id, $gateway->settings );
					if ( $integration instanceof AbstractPaymentGateway ) {
						$integration->initialize();
						$this->register_gateway( $integration );
					}
				} catch ( Exception $e ) {
					Logger::error( 'Autoship Payments Registry', "Failed to register payment gateway {$gateway_id}: " . $e->getMessage() );
				}
			}
		}
	}

	/**
	 * Register a payment gateway.
	 *
	 * @param AbstractPaymentGateway $gateway The gateway to register.
	 * @return void
	 */
	public function register_gateway( AbstractPaymentGateway $gateway ): void {
		$this->gateways[ $gateway->get_method_id() ] = $gateway;
	}

	/**
	 * Get a gateway by ID.
	 *
	 * @param string $gateway_id The gateway ID.
	 * @return AbstractPaymentGateway|null
	 */
	public function get_gateway( string $gateway_id ): ?AbstractPaymentGateway {
		return $this->gateways[ $gateway_id ] ?? null;
	}

	/**
	 * Get all registered gateways.
	 *
	 * @return array
	 */
	public function get_all_gateways(): array {
		return $this->gateways;
	}
}
