<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Service;

use Drupal\ffmpeg_media\Enum\ConversionStatus;
use Drupal\ffmpeg_media\ValueObject\ProgressData;

/**
 * Interface for conversion progress tracking service.
 *
 * @internal Runtime service, not part of the supported contrib extension API.
 */
interface ProgressTrackerInterface {

  /**
   * Starts tracking progress for a media entity.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string|null $correlationId
   *   Optional UUID correlation ID for log tracing.
   * @param string $fieldName
   *   Conversion source field name. Empty string preserves legacy scope.
   */
  public function startTracking(int $mediaId, ?string $correlationId = NULL, string $fieldName = ''): void;

  /**
   * Updates progress for a media entity.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param \Drupal\ffmpeg_media\Enum\ConversionStatus $status
   *   Current conversion status.
   * @param int $percent
   *   Progress percentage (0-100).
   * @param string|null $step
   *   Current step description.
   * @param string|null $currentOutput
   *   Current output format being processed.
   * @param float|null $elapsedSeconds
   *   FFmpeg encoding position in seconds (when duration is unknown).
   * @param string $fieldName
   *   Conversion source field name. Empty string preserves legacy scope.
   */
  public function updateProgress(
    int $mediaId,
    ConversionStatus $status,
    int $percent,
    ?string $step = NULL,
    ?string $currentOutput = NULL,
    ?float $elapsedSeconds = NULL,
    string $fieldName = '',
  ): void;

  /**
   * Marks a conversion as completed.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string $fieldName
   *   Conversion source field name. Empty string updates all rows for media.
   */
  public function markCompleted(int $mediaId, string $fieldName = ''): void;

  /**
   * Marks a conversion as failed.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string $error
   *   Error message.
   * @param string $fieldName
   *   Conversion source field name. Empty string updates all rows for media.
   */
  public function markFailed(int $mediaId, string $error, string $fieldName = ''): void;

  /**
   * Gets the current progress for a media entity.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string $fieldName
   *   Conversion source field name. Empty string returns a best-fit row.
   *
   * @return \Drupal\ffmpeg_media\ValueObject\ProgressData|null
   *   Progress data or NULL if not tracking.
   */
  #[\NoDiscard]
  public function getProgress(int $mediaId, string $fieldName = ''): ?ProgressData;

  /**
   * Gets progress for multiple media entities in a single query.
   *
   * For each media ID, returns the best-fit row using the same selection
   * logic as getProgress() with an empty field name: priority sort by
   * status (converting > pending > failed > completed), then by updated
   * descending.
   *
   * @param array<int, int> $mediaIds
   *   Array of media entity IDs.
   *
   * @return array<int, \Drupal\ffmpeg_media\ValueObject\ProgressData|null>
   *   Progress data keyed by media ID. NULL values for media with no progress.
   */
  #[\NoDiscard]
  public function getMultipleProgress(array $mediaIds): array;

  /**
   * Gets all currently active conversions.
   *
   * @return array<\Drupal\ffmpeg_media\ValueObject\ProgressData>
   *   Array of progress data for active conversions.
   */
  #[\NoDiscard]
  public function getActiveConversions(): array;

  /**
   * Gets count of currently active conversions.
   *
   * @return int
   *   Number of active conversions.
   */
  #[\NoDiscard]
  public function getActiveCount(): int;

  /**
   * Deletes progress record for a specific media entity.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string $fieldName
   *   Conversion source field name. Empty string deletes all rows for media.
   */
  public function deleteProgress(int $mediaId, string $fieldName = ''): void;

  /**
   * Cleans up stale progress records.
   *
   * @param int $maxAge
   *   Maximum age in seconds for completed/failed records.
   *
   * @return int
   *   Number of records cleaned up.
   */
  public function cleanup(int $maxAge = 86400): int;

  /**
   * Gets active conversions that have not been updated within the threshold.
   *
   * Unlike getActiveConversions(), this applies the staleness filter at the
   * DB level instead of loading all active records into memory.
   *
   * @param int $staleThreshold
   *   Unix timestamp. Records with `updated` before this value are stale.
   *
   * @return array<\Drupal\ffmpeg_media\ValueObject\ProgressData>
   *   Array of stale progress data.
   */
  #[\NoDiscard]
  public function getStuckConversions(int $staleThreshold): array;

  /**
   * Marks stuck converting records as failed.
   *
   * Records in CONVERTING status that have not been updated within the
   * given timeout are considered stuck and marked as failed. PENDING
   * records are intentionally excluded because they may be waiting for
   * a queue worker to claim them.
   *
   * @param int $stuckTimeout
   *   Maximum age in seconds before a record is considered stuck.
   *
   * @return int
   *   Number of records marked as failed.
   */
  public function cleanupStuck(int $stuckTimeout = 7200): int;

}
