<?php
/**
 * Connector Automations Bridge
 *
 * Integrates the connector layer with the ambassador-core automations engine.
 *
 * ## How connector actions reach the rule editor
 *
 * Each connector calls register_actions() when it self-registers, which hooks it
 * into `ambh_automation_actions`. ConnectorAutomations adds a late filter on the
 * same hook (priority 99) that strips any action type whose connector is not the
 * currently active connector for that slot. This ensures the rule editor only
 * presents actions from the configured connectors and that switching the active
 * connector immediately changes what is available.
 *
 * ## Full hook contract
 *
 * | Hook                               | Direction           | Handled by                         |
 * |------------------------------------|---------------------|------------------------------------|
 * | `ambh_automation_triggers`         | connector → core    | Connector::register_triggers()     |
 * | `ambh_automation_actions`          | connector → core    | Connector::register_actions()      |
 * |                                    |                     | + ConnectorAutomations (filter 99) |
 * | `ambh_execute_action_{type}`       | core → connector    | ExecutionEngine (already live)     |
 *
 * @package AmbassadorHub\Connectors
 */

namespace AmbassadorHub\Connectors;

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

use function add_filter;

/**
 * Bridges the connector registry with the automations engine.
 *
 * Wired in by ConnectorRegistry after all connectors have self-registered.
 */
final class ConnectorAutomations {

	/**
	 * Register the late filter that enforces active-only action visibility.
	 *
	 * Called by ConnectorRegistry::boot() after connectors have registered.
	 *
	 * @return void
	 */
	public static function init(): void {
		// Priority 99 — runs after all connectors have added their own actions
		// at default priority, giving us a clean list to filter.
		add_filter( 'ambh_automation_actions', array( self::class, 'filter_active_connector_actions' ), 99 );
	}

	/**
	 * Strip action types that belong to inactive connectors.
	 *
	 * Each action definition may carry a `connector_id` key. If present:
	 * - Look up that connector in the registry.
	 * - If it is NOT the active connector for its type, remove it from the list.
	 *
	 * Action definitions without a `connector_id` are left untouched (they
	 * belong to core or to non-connector modules).
	 *
	 * @param array<string, array<string, mixed>> $actions Action definitions keyed by action type ID.
	 * @return array<string, array<string, mixed>>
	 */
	public static function filter_active_connector_actions( array $actions ): array {
		$active_ids = self::get_active_connector_ids();

		foreach ( $actions as $action_type => $definition ) {
			$connector_id = $definition['connector_id'] ?? null;

			if ( null === $connector_id ) {
				// Not a connector-owned action — leave it in.
				continue;
			}

			if ( ! in_array( $connector_id, $active_ids, true ) ) {
				unset( $actions[ $action_type ] );
			}
		}

		return $actions;
	}

	/**
	 * Collect the IDs of all currently active connectors (one per type slot).
	 *
	 * @return string[] Connector IDs that are currently active and available.
	 */
	private static function get_active_connector_ids(): array {
		$ids = array();

		$psp = ConnectorRegistry::get_active_psp();
		if ( $psp ) {
			$ids[] = $psp->get_id();
		}

		$crm = ConnectorRegistry::get_active_crm();
		if ( $crm ) {
			$ids[] = $crm->get_id();
		}

		$marketing = ConnectorRegistry::get_active_marketing();
		if ( $marketing ) {
			$ids[] = $marketing->get_id();
		}

		return $ids;
	}
}
