<?php

/**
 * HandlerRouter â€” maps action IDs to their Domain Handler.
 *
 * This is the routing layer that replaces the monolithic dispatch logic
 * inside ActionExecutor. During the Phase-Out migration, handlers are
 * registered here one domain at a time.
 *
 * The router is stateless: it is safe to instantiate from both the
 * AJAX chat channel (Controller.php) and the MCP channel (mcp-adapter)
 * within the same PHP execution.
 *
 * @package LolaCore\Actions
 * @license GPL-2.0-or-later
 */

declare( strict_types=1 );

namespace LolaCore\Actions;

use LolaCore\Actions\Contracts\ActionHandlerInterface;

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

/**
 * Resolves an action ID to the Domain Handler responsible for it.
 *
 * Usage:
 *   $router  = new HandlerRouter();
 *   $handler = $router->resolve('get_content');
 *   if ( $handler !== null ) {
 *       $result = $handler->handle('get_content', $params, $dryRun);
 *   }
 */
class HandlerRouter {

	/**
	 * Map of action_id â†’ handler instance, built lazily on first call.
	 *
	 * @var array<string, ActionHandlerInterface>
	 */
	private array $map = array();

	/**
	 * Whether the routing map has been built.
	 *
	 * @var bool
	 */
	private bool $initialized = false;

	/**
	 * Build the action-ID â†’ handler map.
	 *
	 * Each handler declares its owned action IDs via getSupportedActions().
	 * If two handlers claim the same ID the first registration wins and a
	 * notice is logged (non-fatal).
	 *
	 * Handlers are added here progressively as the Phase-Out migration
	 * completes each domain. Start with zero handlers â€” ActionExecutor
	 * falls back to its internal methods for everything not yet migrated.
	 *
	 * @return void
	 */
	private function build(): void {
		if ( $this->initialized ) {
			return;
		}

		/** @var ActionHandlerInterface[] $handlers */
		$handlers = array(
			// --- PHASE 1: Low-risk domains (no cross-domain dependencies) ---
			new Handlers\SystemHandler(),
			new Handlers\MetaHandler(),
			new Handlers\TaxonomyHandler(),
			new Handlers\CommentHandler(),
			new Handlers\MediaHandler(),
			new Handlers\SeoHandler(),
			new Handlers\SecurityHandler(),
			// --- PHASE 2: Medium-complexity domains ---
			new Handlers\ContentHandler(),
			new Handlers\NavigationHandler(),
			new Handlers\UserHandler(),
			// --- PHASE 3: Complex domains ---
			new Handlers\PluginHandler(),
			new Handlers\ThemeHandler(),
			new Handlers\WooReadHandler(),
			new Handlers\WooWriteHandler(),
			new Handlers\MemoryHandler(),
			// --- PHASE 4: Skills ---
			new Handlers\SkillsHandler(),
		);

		foreach ( $handlers as $handler ) {
			foreach ( $handler->getSupportedActions() as $actionId ) {
				if ( isset( $this->map[ $actionId ] ) ) {
					// Non-fatal: first registration wins.
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
					if (defined('WP_DEBUG') && WP_DEBUG) { error_log( "[LolaCore HandlerRouter] Duplicate registration for action '{$actionId}' â€” skipping." ); }
					continue;
				}
				$this->map[ $actionId ] = $handler;
			}
		}

		$this->initialized = true;
	}

	/**
	 * Resolve an action ID to its Domain Handler.
	 *
	 * Returns null if no handler has been registered for the given action,
	 * which signals ActionExecutor to fall back to its internal method.
	 *
	 * @param string $actionId Normalized snake_case action ID.
	 * @return ActionHandlerInterface|null The handler, or null if not yet migrated.
	 */
	public function resolve( string $actionId ): ?ActionHandlerInterface {
		$this->build();
		return $this->map[ $actionId ] ?? null;
	}

	/**
	 * Returns all currently registered action IDs (for debugging/testing).
	 *
	 * @return array<string>
	 */
	public function getRegisteredActionIds(): array {
		$this->build();
		return array_keys( $this->map );
	}
}
