<?php
/**
 * Run repository contract.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Repository;

use ScheduledChanges\Domain\Operation\Operation;
use ScheduledChanges\Domain\Run\Run;
use ScheduledChanges\Domain\Shared\UtcTimestamp;
use ScheduledChanges\Validation\ValidationReport;

/**
 * Storage port retained for wpdb and deterministic test implementations.
 * Stores execution attempts and per-operation outcomes. Finders return `null`
 * for not-found; write, transition, and integrity failures throw
 * `RepositoryException`.
 */
interface RunRepository {
	public function create( Run $run ): int;

	public function findById( int $id ): ?Run;

	public function findLatestSuccessfulForVersion( int $version_id ): ?Run;

	/**
	 * @return array<string,array<string,mixed>>
	 */
	public function operationResults( int $run_id ): array;

	public function linkRollback( int $source_run_id, int $rollback_run_id ): void;

	public function nextAttemptNumber( int $version_id, UtcTimestamp $occurrence_at ): int;

	/**
	 * Atomically transitions a run when its current status is allowed.
	 *
	 * @param int                 $id Run ID.
	 * @param string[]            $expected_statuses Allowed current statuses.
	 * @param string              $status New RunStatus value.
	 * @param array<string,mixed> $values Additional columns to update.
	 * @param string[]            $formats Formats for additional columns.
	 */
	public function transition( int $id, array $expected_statuses, string $status, array $values = array(), array $formats = array() ): bool;

	public function markValidating( int $id, UtcTimestamp $started_at ): bool;

	public function markRunning( int $id, ValidationReport $validation ): bool;

	/**
	 * Records one operation result.
	 *
	 * @param int                 $run_id Run ID.
	 * @param int                 $version_id Launch version ID.
	 * @param Operation           $operation Immutable operation.
	 * @param string              $status Result status.
	 * @param int                 $attempt_number Attempt number.
	 * @param UtcTimestamp        $started_at Start time.
	 * @param UtcTimestamp        $completed_at Completion time.
	 * @param array<string,mixed> $result Structured redacted result.
	 * @param string|null         $classification Failure class.
	 * @param bool                $retryable Whether a retry is safe.
	 * @param bool                $verified Whether readback verified.
	 * @param int                 $duration_ms Duration in milliseconds.
	 */
	public function recordOperation(
		int $run_id,
		int $version_id,
		Operation $operation,
		string $status,
		int $attempt_number,
		UtcTimestamp $started_at,
		UtcTimestamp $completed_at,
		array $result,
		?string $classification,
		bool $retryable,
		bool $verified,
		int $duration_ms
	): void;

	public function hasVerifiedSuccess(
		int $version_id,
		string $operation_uuid,
		UtcTimestamp $occurrence_at
	): bool;

	/**
	 * Finalizes one run.
	 *
	 * @param int                 $id Run ID.
	 * @param string              $status Terminal status.
	 * @param ValidationReport    $validation Validation report.
	 * @param array<string,mixed> $result Structured redacted run summary.
	 * @param int                 $warning_count Warning count.
	 * @param int                 $error_count Error count.
	 * @param UtcTimestamp        $completed_at Completion time.
	 */
	public function finalize(
		int $id,
		string $status,
		ValidationReport $validation,
		array $result,
		int $warning_count,
		int $error_count,
		UtcTimestamp $completed_at
	): bool;

	/**
	 * @return array{average_delay_seconds:float,maximum_delay_seconds:int,sample_size:int}
	 */
	public function delayMetrics(): array;

	public function deleteById( int $id ): bool;
}
