<?php
/**
 * Scheduler worker run context.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Scheduler;

use ScheduledChanges\Domain\Launch\Launch;
use ScheduledChanges\Domain\Launch\LaunchVersion;
use ScheduledChanges\Domain\Operation\OperationGraph;
use ScheduledChanges\Domain\Run\Run;
use ScheduledChanges\Domain\Shared\UtcTimestamp;

/**
 * Carries one immutable queue run through validation, execution, and finalization.
 */
final class SchedulerRunContext {
	private Launch $launch;
	private LaunchVersion $version;
	private int $version_id;
	private int $actor_id;
	private int $attempt;
	private UtcTimestamp $scheduled_at;
	private string $lock_token;
	private Run $run;
	private int $run_id;
	/**
	 * @var string[]
	 */
	private array $targets;
	private bool $locked = false;

	/**
	 * Creates a run context.
	 *
	 * @param string[] $targets Lock target references.
	 */
	public function __construct(
		Launch $launch,
		LaunchVersion $version,
		int $version_id,
		int $actor_id,
		int $attempt,
		UtcTimestamp $scheduled_at,
		string $lock_token,
		Run $run,
		int $run_id,
		array $targets
	) {
		$this->launch       = $launch;
		$this->version      = $version;
		$this->version_id   = $version_id;
		$this->actor_id     = $actor_id;
		$this->attempt      = $attempt;
		$this->scheduled_at = $scheduled_at;
		$this->lock_token   = $lock_token;
		$this->run          = $run;
		$this->run_id       = $run_id;
		$this->targets      = $targets;
	}

	/**
	 * Returns the scheduled launch.
	 */
	public function launch(): Launch {
		return $this->launch;
	}

	/**
	 * Returns the immutable launch version.
	 */
	public function version(): LaunchVersion {
		return $this->version;
	}

	/**
	 * Returns the internal launch ID.
	 */
	public function launchId(): int {
		return (int) $this->launch->id();
	}

	/**
	 * Returns the internal version ID.
	 */
	public function versionId(): int {
		return $this->version_id;
	}

	/**
	 * Returns the immutable execution actor.
	 */
	public function actorId(): int {
		return $this->actor_id;
	}

	/**
	 * Returns the queue attempt number.
	 */
	public function attempt(): int {
		return $this->attempt;
	}

	/**
	 * Returns the occurrence timestamp.
	 */
	public function scheduledAt(): UtcTimestamp {
		return $this->scheduled_at;
	}

	/**
	 * Returns the run lock token.
	 */
	public function lockToken(): string {
		return $this->lock_token;
	}

	/**
	 * Returns the persisted run aggregate.
	 */
	public function run(): Run {
		return $this->run;
	}

	/**
	 * Returns the persisted run ID.
	 */
	public function runId(): int {
		return $this->run_id;
	}

	/**
	 * Returns the immutable operation graph.
	 */
	public function graph(): OperationGraph {
		return $this->version->plan()->graph();
	}

	/**
	 * Returns provider requirements for validation.
	 *
	 * @return array<string,string>
	 */
	public function requiredProviders(): array {
		return $this->version->plan()->requiredProviders();
	}

	/**
	 * Returns lock target references.
	 *
	 * @return string[]
	 */
	public function targets(): array {
		return $this->targets;
	}

	/**
	 * Marks locks held by this run.
	 */
	public function markLocked(): void {
		$this->locked = true;
	}

	/**
	 * Marks locks released by this run.
	 */
	public function markLocksReleased(): void {
		$this->locked = false;
	}

	/**
	 * Returns whether locks are currently held.
	 */
	public function locked(): bool {
		return $this->locked;
	}
}
