<?php

declare(strict_types=1);

namespace Drupal\flowdrop_runtime\Service\Storage;

use Drupal\flowdrop_job\FlowDropJobInterface;
use Drupal\flowdrop_pipeline\Entity\FlowDropPipelineRuntimeInterface;

/**
 * Interface for job storage operations.
 *
 * This interface abstracts job persistence, allowing different storage
 * backends (Drupal entities, in-memory, Redis, etc.) to be used
 * interchangeably.
 *
 * Implementations:
 * - DrupalJobStorage: Persistent storage using Drupal entities
 * - InMemoryJobStorage: Fast ephemeral storage for synchronous execution
 * - (Future) RedisJobStorage: Fast persistent storage
 *
 * @internal
 *   This class is not part of the public API and may change without notice.
 */
interface JobStorageInterface {

  /**
   * Creates a new job.
   *
   * @param array $data
   *   The job data with the following keys:
   *   - label: (string) Human-readable label
   *   - bundle: (string) Bundle/type (default: 'default')
   *   - node_id: (string) The workflow node ID
   *   - pipeline_id: (string|int) The parent pipeline ID
   *   - metadata: (array|string) Job metadata (JSON encoded if string)
   *   - status: (string) Initial status (default: 'idle')
   *   - priority: (int) Job priority
   *   - max_retries: (int) Maximum retry count
   *   - dependent_jobs: (array) IDs of jobs this job depends on.
   *
   * @return \Drupal\flowdrop_job\FlowDropJobInterface
   *   The created job (not yet saved).
   */
  public function create(array $data): FlowDropJobInterface;

  /**
   * Loads a job by ID.
   *
   * @param string|int $id
   *   The job ID.
   *
   * @return \Drupal\flowdrop_job\FlowDropJobInterface|null
   *   The job entity, or NULL if not found.
   */
  public function load(string|int $id): ?FlowDropJobInterface;

  /**
   * Loads multiple jobs by ID.
   *
   * @param array $ids
   *   Array of job IDs.
   *
   * @return \Drupal\flowdrop_job\FlowDropJobInterface[]
   *   Array of job entities keyed by ID.
   */
  public function loadMultiple(array $ids): array;

  /**
   * Saves a job.
   *
   * @param \Drupal\flowdrop_job\FlowDropJobInterface $job
   *   The job to save.
   */
  public function save(FlowDropJobInterface $job): void;

  /**
   * Deletes a job.
   *
   * @param \Drupal\flowdrop_job\FlowDropJobInterface $job
   *   The job to delete.
   */
  public function delete(FlowDropJobInterface $job): void;

  /**
   * Gets all jobs for a pipeline.
   *
   * @param \Drupal\flowdrop_pipeline\Entity\FlowDropPipelineRuntimeInterface $pipeline
   *   The pipeline.
   *
   * @return \Drupal\flowdrop_job\FlowDropJobInterface[]
   *   Array of job entities.
   */
  public function getByPipeline(FlowDropPipelineRuntimeInterface $pipeline): array;

  /**
   * Gets jobs for a pipeline filtered by status.
   *
   * @param \Drupal\flowdrop_pipeline\Entity\FlowDropPipelineRuntimeInterface $pipeline
   *   The pipeline.
   * @param string $status
   *   The status to filter by (e.g., 'idle', 'pending', 'completed', 'failed').
   *
   * @return \Drupal\flowdrop_job\FlowDropJobInterface[]
   *   Array of job entities with the specified status.
   */
  public function getByPipelineAndStatus(FlowDropPipelineRuntimeInterface $pipeline, string $status): array;

  /**
   * Gets jobs that are ready to run.
   *
   * A job is ready when:
   * - Its status is 'pending' OR
   * - Its status is 'idle' AND all dependent jobs are completed.
   *
   * @param \Drupal\flowdrop_pipeline\Entity\FlowDropPipelineRuntimeInterface $pipeline
   *   The pipeline.
   *
   * @return \Drupal\flowdrop_job\FlowDropJobInterface[]
   *   Array of ready job entities.
   */
  public function getReadyJobs(FlowDropPipelineRuntimeInterface $pipeline): array;

  /**
   * Resets the storage cache.
   *
   * For entity-based storage, this clears the static entity cache.
   * For in-memory storage, this may be a no-op.
   *
   * @param array|null $ids
   *   Optional array of job IDs to reset. If NULL, reset all.
   */
  public function resetCache(?array $ids = NULL): void;

}
