<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Cdn;

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

/**
 * Interface for CDN integration services.
 *
 * Provides abstraction for uploading converted files to CDN providers
 * and rewriting URLs to serve content from the CDN.
 */
interface CdnIntegrationInterface {

  /**
   * Gets the CDN provider identifier.
   *
   * @return string
   *   Provider ID (e.g., 's3', 'cloudfront', 'gcs').
   */
  public function getProviderId(): string;

  /**
   * Gets the CDN provider label.
   *
   * @return string
   *   Human-readable provider name.
   */
  public function getProviderLabel(): string;

  /**
   * Checks if the CDN integration is properly configured.
   *
   * @return bool
   *   TRUE if configured and ready to use.
   */
  #[\NoDiscard]
  public function isConfigured(): bool;

  /**
   * Validates the CDN configuration and connectivity.
   *
   * @return array{valid: bool, errors: array<string>}
   *   Validation result with any error messages.
   */
  #[\NoDiscard]
  public function validateConfiguration(): array;

  /**
   * Uploads a file to the CDN.
   *
   * @param string $localPath
   *   Local file path.
   * @param string $remotePath
   *   Remote path/key on the CDN.
   * @param array<string, string> $metadata
   *   Optional metadata to attach to the file.
   *
   * @return array{success: bool, url: string|null, error: string|null}
   *   Upload result.
   */
  public function uploadFile(
    string $localPath,
    string $remotePath,
    array $metadata = [],
  ): array;

  /**
   * Uploads all conversion outputs for a media entity.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media entity.
   * @param array<string, string> $outputs
   *   Map of output type to local file path.
   *
   * @return array<string, array{success: bool, url: string|null, error: string|null}>
   *   Upload results keyed by output type.
   */
  public function uploadMediaOutputs(
    MediaInterface $media,
    array $outputs,
  ): array;

  /**
   * Deletes a file from the CDN.
   *
   * @param string $remotePath
   *   Remote path/key on the CDN.
   *
   * @return bool
   *   TRUE if deleted successfully.
   */
  public function deleteFile(string $remotePath): bool;

  /**
   * Deletes all CDN files for a media entity.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media entity.
   *
   * @return int
   *   Number of files deleted.
   */
  public function deleteMediaFiles(MediaInterface $media): int;

  /**
   * Gets the CDN URL for a file.
   *
   * @param string $remotePath
   *   Remote path/key on the CDN.
   *
   * @return string
   *   Full CDN URL.
   */
  #[\NoDiscard]
  public function getCdnUrl(string $remotePath): string;

  /**
   * Rewrites a local URL to a CDN URL.
   *
   * @param string $localUrl
   *   Local file URL.
   *
   * @return string
   *   CDN URL if rewriting is enabled, otherwise original URL.
   */
  #[\NoDiscard]
  public function rewriteUrl(string $localUrl): string;

  /**
   * Generates the remote path for a file.
   *
   * @param \Drupal\file\FileInterface $file
   *   The file entity.
   * @param string|null $outputType
   *   Optional output type (mp4, webm, thumbnail, etc.).
   *
   * @return string
   *   Remote path for the CDN.
   */
  #[\NoDiscard]
  public function generateRemotePath(
    FileInterface $file,
    ?string $outputType = NULL,
  ): string;

  /**
   * Resolves the remote CDN path for a local file URI.
   *
   * Looks up the persisted mapping from local output paths to CDN keys.
   *
   * @param string $uri
   *   Local file URI or path (e.g., 'public://ffmpeg_media/42/video.mp4').
   *
   * @return string|null
   *   Remote CDN key, or NULL when no mapping is known.
   */
  #[\NoDiscard]
  public function resolveRemotePath(string $uri): ?string;

  /**
   * Checks if a file exists on the CDN.
   *
   * @param string $remotePath
   *   Remote path/key on the CDN.
   *
   * @return bool
   *   TRUE if file exists.
   */
  #[\NoDiscard]
  public function fileExists(string $remotePath): bool;

  /**
   * Gets file metadata from the CDN.
   *
   * @param string $remotePath
   *   Remote path/key on the CDN.
   *
   * @return array{content_type: string|null, content_length: int, last_modified: string|null, etag: string|null}|null
   *   File metadata or NULL if not found.
   */
  #[\NoDiscard]
  public function getFileMetadata(string $remotePath): ?array;

  /**
   * Purges CDN cache for a file.
   *
   * @param string $remotePath
   *   Remote path/key on the CDN.
   *
   * @return bool
   *   TRUE if purge request was successful.
   */
  public function purgeCache(string $remotePath): bool;

  /**
   * Purges CDN cache for multiple files.
   *
   * @param array<string> $remotePaths
   *   Remote paths to purge.
   *
   * @return int
   *   Number of successful purge requests.
   */
  public function purgeCacheBatch(array $remotePaths): int;

  /**
   * Gets CDN usage statistics.
   *
   * @return array{
   *   total_files: int,
   *   total_size_bytes: int,
   *   bandwidth_bytes: int|null,
   *   }
   *   Usage statistics.
   */
  #[\NoDiscard]
  public function getUsageStats(): array;

  /**
   * Generates a presigned URL for temporary access to a private file.
   *
   * @param string $remotePath
   *   Remote file path.
   * @param int $expiresIn
   *   Expiration time in seconds (default: 3600).
   *
   * @return string
   *   Presigned URL.
   */
  #[\NoDiscard]
  public function generatePresignedUrl(
    string $remotePath,
    int $expiresIn = 3600,
  ): string;

}
