<?php
/**
 * Gateway Registry.
 *
 * Singleton store that maps gateway slugs to their PHP class names.
 * Gateways register themselves on the `titancart_register_gateways` action
 * which fires during PaymentsModule::init().
 *
 * Usage (third-party gateway):
 *
 *   add_action( 'titancart_register_gateways', function ( $registry ) {
 *       $registry->register( 'mygateway', \MyPlugin\MyGateway::class );
 *   } );
 *
 * Usage (retrieve + instantiate):
 *
 *   $gateway = GatewayRegistry::instance()->make( 'stripe' );
 *
 * @package TitanCart\Modules\Payments
 */

namespace TitanCart\Modules\Payments;

defined( 'ABSPATH' ) || exit;

class GatewayRegistry {

    /** @var GatewayRegistry|null */
    private static ?GatewayRegistry $instance = null;

    /** @var array<string, class-string<PaymentGatewayInterface>> slug → FQCN */
    private array $gateways = [];

    private function __construct() {}

    public static function instance(): self {
        if ( self::$instance === null ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Register a gateway class against a slug.
     *
     * @param  string $slug   Unique key (e.g. 'stripe', 'paypal', 'cod').
     * @param  string $class  Fully-qualified class name implementing PaymentGatewayInterface.
     * @throws \InvalidArgumentException If the class does not implement the interface.
     */
    public function register( string $slug, string $class ): void {
        if ( ! is_a( $class, PaymentGatewayInterface::class, true ) ) {
            throw new \InvalidArgumentException(
                esc_html( "TitanCart GatewayRegistry: '{$class}' must implement PaymentGatewayInterface." )
            );
        }
        $this->gateways[ $slug ] = $class;
    }

    /**
     * Check if a gateway slug is registered.
     *
     * @param  string $slug
     * @return bool
     */
    public function has( string $slug ): bool {
        return isset( $this->gateways[ $slug ] );
    }

    /**
     * Instantiate and return the gateway for a given slug.
     *
     * @param  string $slug
     * @return PaymentGatewayInterface|null  Null if slug not registered.
     */
    public function make( string $slug ): ?PaymentGatewayInterface {
        if ( ! $this->has( $slug ) ) {
            return null;
        }
        $class = $this->gateways[ $slug ];
        return new $class();
    }

    /**
     * Return all registered gateway slugs.
     *
     * @return string[]
     */
    public function slugs(): array {
        return array_keys( $this->gateways );
    }

    /**
     * Return the full registry map (slug → class name).
     *
     * @return array<string, string>
     */
    public function all(): array {
        return $this->gateways;
    }
}
