<?php
/**
 * Execution snapshot and conflict guard.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Execution;

use ScheduledChanges\Snapshot\SnapshotCoordinator;

use ScheduledChanges\Domain\Operation\Operation;
use ScheduledChanges\Domain\Operation\OperationGraph;
use ScheduledChanges\Domain\Operation\TargetDefinition;
use ScheduledChanges\Domain\Snapshot\SnapshotKind;

/**
 * Runs just-in-time snapshot and field-conflict checks around operation execution.
 */
final class ExecutionGuard {
	private SnapshotCoordinator $snapshots;
	private ConflictDetector $conflicts;
	public function __construct( SnapshotCoordinator $snapshots, ConflictDetector $conflicts ) {
		$this->snapshots = $snapshots;
		$this->conflicts = $conflicts;
	}

	public function begin(
		int $run_id,
		int $version_id,
		OperationGraph $graph,
		ExecutionState $state
	): void {
		$this->snapshots->capture(
			$run_id,
			$version_id,
			$graph,
			$state,
			SnapshotKind::PRE_EXECUTION
		);
	}

	public function beforeOperation(
		Operation $operation,
		TargetDefinition $target,
		ExecutionState $state
	): ?OperationExecutionResult {
		$decision = $this->conflicts->decide( $operation, $target, $state );
		$state->recordConflict( $operation->uuid()->value(), $decision->details() );

		if ( ! $decision->shouldProceed() ) {
			return $decision->result();
		}

		$state->setDesiredValue( $operation->uuid()->value(), $decision->desiredValue() );

		return null;
	}

	public function complete(
		int $run_id,
		int $version_id,
		OperationGraph $graph,
		ExecutionState $state
	): void {
		$this->snapshots->capture(
			$run_id,
			$version_id,
			$graph,
			$state,
			SnapshotKind::POST_EXECUTION
		);
	}
}
