<?php

declare(strict_types=1);

namespace Drupal\eb\Result;

/**
 * Aggregate result object for complete operation lifecycle.
 *
 * Combines validation, preview, execution, and rollback results.
 */
final class OperationResult {

  /**
   * Constructor.
   *
   * @param \Drupal\eb\Result\ValidationResult $validationResult
   *   The validation result.
   * @param \Drupal\eb\Result\PreviewResult|null $previewResult
   *   The preview result (optional).
   * @param \Drupal\eb\Result\ExecutionResult|null $executionResult
   *   The execution result (optional).
   * @param \Drupal\eb\Result\RollbackResult|null $rollbackResult
   *   The rollback result (optional).
   */
  public function __construct(
    protected ValidationResult $validationResult,
    protected ?PreviewResult $previewResult = NULL,
    protected ?ExecutionResult $executionResult = NULL,
    protected ?RollbackResult $rollbackResult = NULL,
  ) {}

  /**
   * Gets the validation result.
   */
  public function getValidationResult(): ValidationResult {
    return $this->validationResult;
  }

  /**
   * Gets the preview result.
   */
  public function getPreviewResult(): ?PreviewResult {
    return $this->previewResult;
  }

  /**
   * Sets the preview result.
   */
  public function setPreviewResult(PreviewResult $previewResult): self {
    $this->previewResult = $previewResult;
    return $this;
  }

  /**
   * Gets the execution result.
   */
  public function getExecutionResult(): ?ExecutionResult {
    return $this->executionResult;
  }

  /**
   * Sets the execution result.
   */
  public function setExecutionResult(ExecutionResult $executionResult): self {
    $this->executionResult = $executionResult;
    return $this;
  }

  /**
   * Gets the rollback result.
   */
  public function getRollbackResult(): ?RollbackResult {
    return $this->rollbackResult;
  }

  /**
   * Sets the rollback result.
   */
  public function setRollbackResult(RollbackResult $rollbackResult): self {
    $this->rollbackResult = $rollbackResult;
    return $this;
  }

  /**
   * Checks if validation passed.
   */
  public function isValid(): bool {
    return $this->validationResult->isValid();
  }

  /**
   * Checks if execution was successful.
   */
  public function isExecuted(): bool {
    return $this->executionResult !== NULL && $this->executionResult->isSuccess();
  }

  /**
   * Checks if operation was rolled back.
   */
  public function isRolledBack(): bool {
    return $this->rollbackResult !== NULL && $this->rollbackResult->isSuccess();
  }

  /**
   * Gets all messages from all stages.
   *
   * @return array<string>
   *   Array of messages.
   */
  public function getAllMessages(): array {
    $messages = [];

    // Validation messages.
    if (!$this->validationResult->isValid()) {
      foreach ($this->validationResult->getErrors() as $error) {
        $messages[] = '[Validation] ' . $error['message'];
      }
    }

    // Preview messages.
    if ($this->previewResult !== NULL) {
      foreach ($this->previewResult->getWarnings() as $message) {
        $messages[] = '[Preview] ' . $message;
      }
    }

    // Execution messages.
    if ($this->executionResult !== NULL) {
      foreach ($this->executionResult->getMessages() as $message) {
        $messages[] = '[Execution] ' . $message;
      }
    }

    // Rollback messages.
    if ($this->rollbackResult !== NULL) {
      foreach ($this->rollbackResult->getMessages() as $message) {
        $messages[] = '[Rollback] ' . $message;
      }
    }

    return $messages;
  }

  /**
   * Gets summary of operation status.
   *
   * @return array<string, mixed>
   *   Summary information.
   */
  public function getSummary(): array {
    return [
      'valid' => $this->isValid(),
      'executed' => $this->isExecuted(),
      'rolled_back' => $this->isRolledBack(),
      'validation_errors' => $this->validationResult->isValid() ? 0 : count($this->validationResult->getErrors()),
      'preview_available' => $this->previewResult !== NULL,
      'execution_success' => $this->executionResult?->isSuccess() ?? FALSE,
      'rollback_success' => $this->rollbackResult?->isSuccess() ?? FALSE,
      'message_count' => count($this->getAllMessages()),
    ];
  }

}
