<?php

namespace SugarCalendarBookings\Migration;

use SugarCalendarBookings\Plugin;

/**
 * Migration Registry.
 *
 * Unified registry for migration source adapters and their UI configs.
 * Follows the same pattern as TaskRegistry and PaymentGatewayRegistry.
 *
 * @since 1.3.0
 */
class MigrationRegistry {

	/**
	 * Registered adapters.
	 *
	 * @since 1.3.0
	 *
	 * @var array<string, SourceAdapterInterface>
	 */
	private array $adapters = [];

	/**
	 * Registered UI configs.
	 *
	 * @since 1.3.0
	 *
	 * @var array<string, MigrationUIConfigInterface>
	 */
	private array $ui_configs = [];

	/**
	 * Register migration sources.
	 *
	 * Each source is defined as an array with 'adapter' and 'ui_config' class names.
	 * The UI config will be instantiated with the adapter as a dependency.
	 *
	 * @since 1.3.0
	 *
	 * @param array<array{adapter: class-string<SourceAdapterInterface>, ui_config: class-string<MigrationUIConfigInterface>}> $sources Migration sources.
	 */
	public function register_sources( array $sources ): void {

		foreach ( $sources as $source ) {
			if ( ! isset( $source['adapter'], $source['ui_config'] ) ) {
				continue;
			}

			$adapter_class   = $source['adapter'];
			$ui_config_class = $source['ui_config'];

			// Validate adapter class.
			if ( ! class_exists( $adapter_class ) || ! is_subclass_of( $adapter_class, SourceAdapterInterface::class ) ) {
				continue;
			}

			// Validate UI config class.
			if ( ! class_exists( $ui_config_class ) || ! is_subclass_of( $ui_config_class, MigrationUIConfigInterface::class ) ) {
				continue;
			}

			// Instantiate adapter via container.
			$adapter = Plugin::get( $adapter_class );

			// Instantiate UI config with adapter dependency.
			$ui_config = new $ui_config_class( $adapter );

			// Register both.
			$this->adapters[ $adapter->get_id() ]   = $adapter;
			$this->ui_configs[ $adapter->get_id() ] = $ui_config;
		}
	}

	/**
	 * Get adapter by ID.
	 *
	 * @since 1.3.0
	 *
	 * @param string $id Adapter ID.
	 *
	 * @return SourceAdapterInterface|null
	 */
	public function get_adapter( string $id ): ?SourceAdapterInterface {

		return $this->adapters[ $id ] ?? null;
	}

	/**
	 * Get all adapters.
	 *
	 * @since 1.3.0
	 *
	 * @return array<string, SourceAdapterInterface>
	 */
	public function get_adapters(): array {

		return $this->adapters;
	}

	/**
	 * Get UI config by source ID.
	 *
	 * @since 1.3.0
	 *
	 * @param string $source_id Source adapter ID.
	 *
	 * @return MigrationUIConfigInterface|null
	 */
	public function get_ui_config( string $source_id ): ?MigrationUIConfigInterface {

		return $this->ui_configs[ $source_id ] ?? null;
	}

	/**
	 * Get all UI configs.
	 *
	 * @since 1.3.0
	 *
	 * @return array<string, MigrationUIConfigInterface>
	 */
	public function get_ui_configs(): array {

		return $this->ui_configs;
	}

	/**
	 * Get all available UI configs.
	 *
	 * Filters to only return configs where is_available() returns true.
	 *
	 * @since 1.3.0
	 *
	 * @return array<string, MigrationUIConfigInterface>
	 */
	public function get_available_ui_configs(): array {

		return array_filter(
			$this->ui_configs,
			fn( MigrationUIConfigInterface $config ) => $config->is_available()
		);
	}
}
