<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Service;

use Drupal\file\FileInterface;
use Drupal\media\MediaInterface;

/**
 * Interface for video conversion queue management service.
 *
 * @internal Runtime service, not part of the supported contrib extension API.
 */
interface QueueManagerInterface {

  /**
   * Queue name for standard video conversions.
   */
  public const string QUEUE_NAME = 'ffmpeg_media_conversion';

  /**
   * Queue name for large file conversions.
   */
  public const string QUEUE_LARGE_NAME = 'ffmpeg_media_conversion_large';

  /**
   * Default large file threshold in bytes (100MB).
   */
  public const int DEFAULT_LARGE_FILE_THRESHOLD = 104857600;

  /**
   * Queues a media entity for conversion.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media entity to queue.
   * @param string $operation
   *   Operation type: 'convert' or 'reconvert'.
   * @param string|null $profileId
   *   Optional conversion profile ID.
   * @param array<string> $selectedOutputs
   *   Optional array of selected output formats (e.g., ['mp4', 'hls']).
   *   If empty, all profile outputs are used.
   * @param array{segment_duration?: int, playlist_type?: string, representations?: array<int, array{name: string, width: int, height: int, bitrate: string, audio_bitrate: string}>} $streamingOptions
   *   Optional streaming configuration overrides for HLS/DASH outputs.
   *   Keys: segment_duration, playlist_type, representations.
   * @param string $fieldName
   *   Source field name. Empty string for auto-detection.
   *
   * @return bool
   *   TRUE if successfully queued, FALSE if already queued.
   */
  public function queueForConversion(
    MediaInterface $media,
    string $operation = 'convert',
    ?string $profileId = NULL,
    array $selectedOutputs = [],
    array $streamingOptions = [],
    string $fieldName = '',
  ): bool;

  /**
   * Checks if a media entity is currently queued.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string $fieldName
   *   Optional source field name. Empty string checks any queued item.
   *
   * @return bool
   *   TRUE if queued.
   */
  #[\NoDiscard]
  public function isQueued(int $mediaId, string $fieldName = ''): bool;

  /**
   * Returns the number of tracked queue items currently queued for conversion.
   *
   * Uses the dedup marker table as authoritative source, which tracks
   * only genuinely queued items (unlike Drupal's queue backend which
   * may contain orphaned entries after processing).
   *
   * @return int
   *   Number of tracked queue items.
   */
  #[\NoDiscard]
  public function getQueuedMediaCount(): int;

  /**
   * Removes a media entity from the queue.
   *
   * @param int $mediaId
   *   The media entity ID.
   * @param string $fieldName
   *   Optional source field name. Empty string removes all queued items.
   */
  public function removeFromQueue(int $mediaId, string $fieldName = ''): void;

  /**
   * Gets queue statistics.
   *
   * @return array{
   *   total_queued: int,
   *   pending: int,
   *   processing: int,
   *   oldest_item: int|null,
   *   standard_queue: int,
   *   large_queue: int
   *   }
   *   Statistics array with keys for both queues.
   */
  #[\NoDiscard]
  public function getQueueStats(): array;

  /**
   * Gets currently queued media IDs from the deduplication table.
   *
   * Returned in queue insertion order (oldest first).
   *
   * @return array<int, int>
   *   Sequential list of media IDs.
   */
  #[\NoDiscard]
  public function getQueuedMediaIds(): array;

  /**
   * Gets queued queue-item IDs from the deduplication table.
   *
   * Returned in queue insertion order (oldest first).
   *
   * @return array<int, string>
   *   Sequential list of queue item IDs.
   */
  #[\NoDiscard]
  public function getQueuedItemIds(): array;

  /**
   * Gets queued media IDs for a specific queue in insertion order.
   *
   * Uses persisted queue assignments to remain backend-agnostic when queue
   * backends do not expose internal item storage tables.
   *
   * @param string $queueName
   *   Queue plugin ID / queue name.
   *
   * @return array<int, int>
   *   Sequential list of media IDs for the requested queue.
   */
  #[\NoDiscard]
  public function getQueuedMediaIdsForQueue(string $queueName): array;

  /**
   * Gets queued queue-item IDs for a specific queue in insertion order.
   *
   * @param string $queueName
   *   Queue plugin ID / queue name.
   *
   * @return array<int, string>
   *   Sequential list of queue item IDs.
   */
  #[\NoDiscard]
  public function getQueuedItemIdsForQueue(string $queueName): array;

  /**
   * Gets the appropriate queue name based on file size.
   *
   * @param int $fileSize
   *   File size in bytes.
   *
   * @return string
   *   Queue name to use.
   */
  #[\NoDiscard]
  public function getQueueNameForSize(int $fileSize): string;

  /**
   * Gets the appropriate queue for a file.
   *
   * @param \Drupal\file\FileInterface $file
   *   The file entity.
   *
   * @return string
   *   Queue name to use.
   */
  #[\NoDiscard]
  public function getQueueForFile(FileInterface $file): string;

  /**
   * Checks if conversion limit is reached.
   *
   * @return bool
   *   TRUE if concurrent limit reached.
   */
  #[\NoDiscard]
  public function isLimitReached(): bool;

  /**
   * Gets the large file threshold in bytes.
   *
   * @return int
   *   Threshold in bytes.
   */
  #[\NoDiscard]
  public function getLargeFileThreshold(): int;

  /**
   * Cleans up stuck conversions.
   *
   * @return int
   *   Number of stuck conversions cleaned up.
   */
  public function cleanupStuckConversions(): int;

  /**
   * Processes a media entity immediately without queue (sync conversion).
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media entity to convert.
   * @param string|null $profileId
   *   Optional conversion profile ID.
   * @param string $fieldName
   *   Optional source field name. Empty string preserves the legacy
   *   media-wide fallback and resolves the preferred context.
   *
   * @return bool
   *   TRUE if conversion was successful, FALSE otherwise.
   */
  public function processImmediately(MediaInterface $media, ?string $profileId = NULL, string $fieldName = ''): bool;

  /**
   * Cleans up stale deduplication entries.
   *
   * Removes entries from the dedup table that are older than the specified
   * max age, preventing orphaned entries from blocking future conversions.
   *
   * @param int $maxAge
   *   Maximum age in seconds before an entry is considered stale.
   *
   * @return int
   *   Number of stale entries removed.
   */
  public function cleanupStaleQueueEntries(int $maxAge): int;

}
