<?php
/**
 * Scheduling and queue orchestration module boundary.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Scheduler;

use ScheduledChanges\Execution\ExecutionEngine;
use ScheduledChanges\Execution\RetryPolicy;
use ScheduledChanges\Lock\LockManager;
use ScheduledChanges\Provider\ProviderManager;
use ScheduledChanges\Repository\AuditRepository;
use ScheduledChanges\Repository\LaunchRepository;
use ScheduledChanges\Repository\LaunchVersionRepository;
use ScheduledChanges\Repository\RunRepository;
use ScheduledChanges\Validation\PlanValidator;

/**
 * Builds and registers provider-neutral queue services.
 */
final class SchedulingModule {
	public const MODULE_ID = 'scheduled-changes-scheduling';

	public function createServices(
		ProviderManager $providers,
		LaunchRepository $launches,
		LaunchVersionRepository $versions,
		RunRepository $runs,
		AuditRepository $audit,
		PlanValidator $validator,
		LockManager $locks,
		ExecutionEngine $engine,
		?ActionSchedulerGateway $actions = null,
		?CurrentActionContext $action_context = null,
		?SchedulerWorker $worker = null,
		?RecurrenceSafetyValidator $recurrence = null,
		?RetryPolicy $retry_policy = null,
		?EnvironmentFingerprint $environment = null
	): SchedulingServices {
		$actions        ??= new WordPressActionSchedulerGateway();
		$action_context ??= new CurrentActionContext();

		$worker  ??= new SchedulerWorker(
			$providers,
			$launches,
			$versions,
			$runs,
			$audit,
			$validator,
			$locks,
			$engine,
			$actions,
			$action_context,
			$retry_policy,
			$environment
		);
		$scheduler = new SchedulerService(
			$launches,
			$versions,
			$audit,
			$validator,
			$actions,
			$locks,
			$recurrence,
			null,
			$runs
		);

		$lifecycleRepair = isset( $GLOBALS['wpdb'] ) && $GLOBALS['wpdb'] instanceof \wpdb
			? new LifecycleRepairDiagnostics()
			: null;

		return new SchedulingServices(
			$actions,
			$action_context,
			$worker,
			$scheduler,
			new QueueMonitor( $actions, $runs, $locks, $versions, $lifecycleRepair )
		);
	}

	/**
	 * Registers WordPress hooks owned by scheduling and queue orchestration.
	 */
	public function registerHooks( SchedulingServices $services ): void {
		$services->actionContext()->register();

		add_action(
			WordPressActionSchedulerGateway::HOOK,
			array( $services->worker(), 'handle' ),
			10,
			5
		);

		$services->queue()->register();
	}
}
