<?php

declare(strict_types=1);

namespace Drupal\flowdrop_workflow;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\SynchronizableInterface;

/**
 * Storage-neutral contract for a FlowDrop workflow definition.
 *
 * This is the interface every workflow backend implements, regardless of how
 * it is stored. Today the only implementation is the config entity
 * (FlowDropWorkflow, via FlowDropWorkflowInterface); a future revisionable
 * content-entity backend will implement this same contract, so executors,
 * launchers, the schema snapshotter, and other consumers can stay agnostic to
 * storage.
 *
 * Consumers that must accept any backend should type-hint this interface;
 * code that specifically needs a config workflow keeps using
 * FlowDropWorkflowInterface (which extends this one alongside
 * ConfigEntityInterface).
 *
 * Backwards-compatible additions (new methods on a default-implemented trait,
 * new optional parameters) may occur in minor releases; signature changes
 * follow FlowDrop's semver policy.
 *
 * @api
 */
interface WorkflowDefinitionInterface extends EntityInterface, SynchronizableInterface {

  /**
   * Gets the workflow label.
   *
   * @return string
   *   The workflow label.
   */
  public function getLabel(): string;

  /**
   * Sets the workflow label.
   *
   * @param string $label
   *   The workflow label.
   *
   * @return static
   *   The workflow entity.
   */
  public function setLabel(string $label): static;

  /**
   * Gets the workflow description.
   *
   * @return string
   *   The workflow description.
   */
  public function getDescription(): string;

  /**
   * Sets the workflow description.
   *
   * @param string $description
   *   The workflow description.
   *
   * @return static
   *   The workflow entity.
   */
  public function setDescription(string $description): static;

  /**
   * Gets the workflow nodes.
   *
   * @return array
   *   The workflow nodes.
   */
  public function getNodes(): array;

  /**
   * Sets the workflow nodes.
   *
   * @param array $nodes
   *   The workflow nodes.
   *
   * @return static
   *   The workflow entity.
   */
  public function setNodes(array $nodes): static;

  /**
   * Gets the workflow edges.
   *
   * @return array
   *   The workflow edges.
   */
  public function getEdges(): array;

  /**
   * Sets the workflow edges.
   *
   * @param array $edges
   *   The workflow edges.
   *
   * @return static
   *   The workflow entity.
   */
  public function setEdges(array $edges): static;

  /**
   * Gets the workflow metadata.
   *
   * @return array
   *   The workflow metadata.
   */
  public function getMetadata(): array;

  /**
   * Sets the workflow metadata.
   *
   * @param array $metadata
   *   The workflow metadata.
   *
   * @return static
   *   The workflow entity.
   */
  public function setMetadata(array $metadata): static;

  /**
   * Gets the creation timestamp.
   *
   * @return int
   *   The creation timestamp.
   */
  public function getCreated(): int;

  /**
   * Sets the creation timestamp.
   *
   * @param int $created
   *   The creation timestamp.
   *
   * @return static
   *   The workflow entity.
   */
  public function setCreated(int $created): static;

  /**
   * Gets the last modified timestamp.
   *
   * @return int
   *   The last modified timestamp.
   */
  public function getChanged(): int;

  /**
   * Sets the last modified timestamp.
   *
   * @param int $changed
   *   The last modified timestamp.
   *
   * @return static
   *   The workflow entity.
   */
  public function setChanged(int $changed): static;

  /**
   * Gets the user ID who created the workflow.
   *
   * @return int
   *   The user ID.
   */
  public function getUid(): int;

  /**
   * Sets the user ID who created the workflow.
   *
   * @param int $uid
   *   The user ID.
   *
   * @return static
   *   The workflow entity.
   */
  public function setUid(int $uid): static;

  /**
   * Returns whether the workflow is enabled (active).
   *
   * Storage-neutral status accessor. The config-entity backend satisfies this
   * directly via ConfigEntityInterface::status(); a content-entity backend
   * supplies its own status (e.g. backed by a stored flag, or always TRUE).
   * Left untyped to stay signature-compatible with
   * ConfigEntityInterface::status() under the FlowDropWorkflowInterface
   * diamond.
   *
   * @return bool
   *   TRUE if the workflow is enabled, FALSE otherwise.
   */
  public function status();

  /**
   * Gets the complete graph data including nodes and edges.
   *
   * This provides a unified accessor for the workflow graph structure,
   * combining nodes and edges into a single array for graph processing.
   *
   * @return array{nodes: array<mixed>, edges: array<mixed>}
   *   An array containing:
   *   - 'nodes': The workflow nodes array.
   *   - 'edges': The workflow edges array.
   */
  public function getGraphData(): array;

  /**
   * Gets the workflow's declared input ports (exposure map).
   *
   * Each entry maps a caller-visible input name to a specific node/port inside
   * the workflow. Source of truth for translating named inputs to internal
   * initialData at runtime.
   *
   * @return list<array{name: string, node_id: string, port: string}>
   *   The list of input port exposures. Empty when no inputs are declared.
   */
  public function getInputPorts(): array;

  /**
   * Sets the workflow's input port exposure map.
   *
   * @param array<int, array{name: string, node_id: string, port: string}>|null $ports
   *   The exposure entries, or NULL to clear.
   *
   * @return static
   */
  public function setInputPorts(?array $ports): static;

  /**
   * Gets the workflow's declared output ports (exposure map).
   *
   * @return list<array{name: string, node_id: string, port: string}>
   *   The list of output port exposures. Empty when no outputs are declared.
   */
  public function getOutputPorts(): array;

  /**
   * Sets the workflow's output port exposure map.
   *
   * @param array<int, array{name: string, node_id: string, port: string}>|null $ports
   *   The exposure entries, or NULL to clear.
   *
   * @return static
   */
  public function setOutputPorts(?array $ports): static;

  /**
   * Gets the stored parameter schema snapshot.
   *
   * Returns the JSON Schema-shaped contract assembled from the input port
   * exposure map at the last exposure-changing save. The snapshot is
   * annotation-free (title/description stripped) and constrained to the
   * FlowDrop Schema contract subset documented in the workflow schema plan.
   *
   * @return array<string, mixed>|null
   *   The parameter schema snapshot, or NULL when no inputs are declared.
   */
  public function getParameterSchema(): ?array;

  /**
   * Gets the stored output schema snapshot.
   *
   * @return array<string, mixed>|null
   *   The output schema snapshot, or NULL when no outputs are declared.
   */
  public function getOutputSchema(): ?array;

  /**
   * Gets the schema version (semver string).
   *
   * Format MAJOR.MINOR.PATCH. Starts at "0.0.0" when no interface is declared
   * and bumps according to WorkflowSchemaDiffer's classification on each
   * exposure-changing save.
   *
   * @return string
   *   The semver string (e.g. "1.2.0").
   */
  public function getSchemaVersion(): string;

  /**
   * Sets the parameter schema snapshot.
   *
   * Called by WorkflowSchemaSnapshotterInterface during the presave hook —
   * not part of the user-facing API surface.
   *
   * @param array<string, mixed>|null $schema
   *   The new snapshot, or NULL to clear.
   *
   * @internal
   */
  public function setParameterSchema(?array $schema): static;

  /**
   * Sets the output schema snapshot.
   *
   * @param array<string, mixed>|null $schema
   *   The new snapshot, or NULL to clear.
   *
   * @internal
   */
  public function setOutputSchema(?array $schema): static;

  /**
   * Sets the schema version string.
   *
   * @param string $version
   *   A semver MAJOR.MINOR.PATCH string.
   *
   * @internal
   */
  public function setSchemaVersion(string $version): static;

  /**
   * Forces the next save to rebuild the schema snapshot.
   *
   * The rebuild happens regardless of whether the exposure map changed.
   * Used by the drift banner's "Refresh schema" action. Transient runtime
   * state — not persisted on the entity.
   *
   * @internal
   */
  public function setSchemaRebuildForced(bool $forced): static;

  /**
   * Returns whether the next save should force a snapshot rebuild.
   *
   * @internal
   */
  public function isSchemaRebuildForced(): bool;

}
