<?php

declare(strict_types=1);

namespace Drupal\eb\Result;

/**
 * Value object representing execution results.
 */
final class ExecutionResult {

  /**
   * Constructor.
   *
   * @param bool $successful
   *   Whether execution was successful.
   * @param array<int, array<string, mixed>> $affectedEntities
   *   Entities that were affected by execution.
   * @param array<string, mixed> $rollbackData
   *   Data needed to rollback this operation.
   * @param array<int, string> $messages
   *   Informational messages about execution.
   * @param array<int, string> $errors
   *   Errors encountered during execution.
   * @param int $timestamp
   *   Unix timestamp of execution.
   */
  public function __construct(
    protected bool $successful = FALSE,
    protected array $affectedEntities = [],
    protected array $rollbackData = [],
    protected array $messages = [],
    protected array $errors = [],
    protected int $timestamp = 0,
  ) {
    if ($this->timestamp === 0) {
      $this->timestamp = time();
    }
  }

  /**
   * Checks if execution was successful.
   */
  public function isSuccessful(): bool {
    return $this->successful;
  }

  /**
   * Alias for isSuccessful().
   */
  public function isSuccess(): bool {
    return $this->isSuccessful();
  }

  /**
   * Gets affected entities.
   *
   * @return array<int, array<string, mixed>>
   *   Array of entity information.
   */
  public function getAffectedEntities(): array {
    return $this->affectedEntities;
  }

  /**
   * Gets rollback data.
   *
   * @return array<string, mixed>
   *   Rollback data array.
   */
  public function getRollbackData(): array {
    return $this->rollbackData;
  }

  /**
   * Gets execution messages.
   *
   * @return array<int, string>
   *   Array of messages.
   */
  public function getMessages(): array {
    return $this->messages;
  }

  /**
   * Gets execution timestamp.
   */
  public function getTimestamp(): int {
    return $this->timestamp;
  }

  /**
   * Adds an affected entity.
   *
   * @param array<string, mixed> $entityInfo
   *   Entity information.
   */
  public function addAffectedEntity(array $entityInfo): void {
    $this->affectedEntities[] = $entityInfo;
  }

  /**
   * Adds a message.
   *
   * @param string $message
   *   Informational message.
   */
  public function addMessage(string $message): void {
    $this->messages[] = $message;
  }

  /**
   * Adds an affected entity by entity type and ID.
   *
   * @param string $entityType
   *   The entity type.
   * @param string $entityId
   *   The entity ID.
   */
  public function addAffectedEntityById(string $entityType, string $entityId): void {
    $this->affectedEntities[] = [
      'entity_type' => $entityType,
      'entity_id' => $entityId,
    ];
  }

  /**
   * Sets rollback data.
   *
   * @param array<string, mixed> $data
   *   Rollback data.
   */
  public function setRollbackData(array $data): void {
    $this->rollbackData = $data;
  }

  /**
   * Gets errors.
   *
   * @return array<int, string>
   *   Array of error messages.
   */
  public function getErrors(): array {
    return $this->errors;
  }

  /**
   * Adds an error.
   *
   * @param string $error
   *   Error message.
   */
  public function addError(string $error): void {
    $this->errors[] = $error;
    $this->successful = FALSE;
  }

}
