<?php
/**
 * Tracking Provider Registry
 *
 * @package AmbassadorHub\Tracking
 */

namespace AmbassadorHub\Tracking;

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

/**
 * Collects and caches registered tracking providers.
 *
 * Providers register themselves via the ambh_tracking_providers filter.
 * The result is resolved and cached on first call to get_providers().
 */
final class TrackingRegistry {

	/**
	 * Resolved provider instances, keyed by provider ID.
	 *
	 * Null before first resolution.
	 *
	 * @var array<string, TrackingProviderInterface>|null
	 */
	private static ?array $providers = null;

	/**
	 * Get all registered providers.
	 *
	 * Resolves providers from the ambh_tracking_providers filter on first call
	 * and caches the result for subsequent calls within the same request.
	 *
	 * @return array<string, TrackingProviderInterface> Providers keyed by ID.
	 */
	public static function get_providers(): array {
		if ( null === self::$providers ) {
			self::$providers = self::resolve_providers();
		}

		return self::$providers;
	}

	/**
	 * Reset the provider cache.
	 *
	 * Useful for testing or when providers are registered late.
	 *
	 * @return void
	 */
	public static function reset(): void {
		self::$providers = null;
	}

	/**
	 * Resolve providers from the filter and validate them.
	 *
	 * @return array<string, TrackingProviderInterface>
	 */
	private static function resolve_providers(): array {
		/**
		 * Filter the list of active tracking providers.
		 *
		 * Each item must implement TrackingProviderInterface. Invalid entries
		 * are silently discarded.
		 *
		 * Example — register a custom provider:
		 *
		 *   add_filter( 'ambh_tracking_providers', function( array $providers ): array {
		 *       $providers[] = new MyProvider();
		 *       return $providers;
		 *   } );
		 *
		 * @since 0.4.0
		 *
		 * @param TrackingProviderInterface[] $providers Empty array by default.
		 */
		$raw = apply_filters( 'ambh_tracking_providers', array() );

		if ( ! is_array( $raw ) ) {
			return array();
		}

		$providers = array();
		foreach ( $raw as $provider ) {
			if ( ! $provider instanceof TrackingProviderInterface ) {
				continue;
			}
			$providers[ $provider->get_id() ] = $provider;
		}

		return $providers;
	}
}
