<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Cdn;

/**
 * AWS Signature V4 request signing and S3 HTTP transport.
 *
 * Handles signing, URL construction, HTTP transport, presigned URLs,
 * and CloudFront invalidation for S3-compatible storage providers.
 */
interface S3RequestSignerInterface {

  /**
   * Makes an S3 API request using cURL.
   *
   * @param string $method
   *   HTTP method (GET, PUT, POST, DELETE, HEAD).
   * @param string $path
   *   Object path (may include query string).
   * @param array<string, string> $headers
   *   Request headers (including signed auth headers).
   * @param string|resource|null $body
   *   Request body or stream resource.
   * @param int|null $contentLength
   *   Content length for streamed uploads.
   *
   * @return array{status: int, headers: array<string, string>, body: string}
   *   Response data.
   *
   * @throws \RuntimeException
   *   On cURL errors.
   * @throws \InvalidArgumentException
   *   If URL or method is empty.
   */
  public function makeRequest(
    string $method,
    string $path,
    array $headers,
    mixed $body = NULL,
    ?int $contentLength = NULL,
  ): array;

  /**
   * Signs a request using AWS Signature V4.
   *
   * @param string $method
   *   HTTP method.
   * @param string $path
   *   Object path.
   * @param string|null $payloadHash
   *   SHA-256 hash of the payload (NULL for empty payload).
   * @param string $queryString
   *   Optional canonical query string.
   *
   * @return array<string, string>
   *   Signed headers including Authorization.
   */
  #[\NoDiscard]
  public function signRequest(
    string $method,
    string $path,
    ?string $payloadHash = NULL,
    string $queryString = '',
  ): array;

  /**
   * Signs an upload request with content type, metadata, and ACL headers.
   *
   * @param string $path
   *   Object path.
   * @param string $contentType
   *   Content type.
   * @param array<string, string> $metadata
   *   Object metadata.
   * @param string $payloadHash
   *   SHA-256 hash of the payload.
   * @param int $contentLength
   *   Content length in bytes.
   *
   * @return array<string, string>
   *   Signed headers for upload.
   */
  #[\NoDiscard]
  public function signUploadRequest(
    string $path,
    string $contentType,
    array $metadata,
    string $payloadHash,
    int $contentLength,
  ): array;

  /**
   * Builds the S3 URL for a path.
   *
   * @param string $path
   *   Object path (may include query string).
   *
   * @return string
   *   Full S3 URL.
   */
  #[\NoDiscard]
  public function buildUrl(string $path): string;

  /**
   * 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: 1 hour, max: 7 days).
   *
   * @return string
   *   Presigned URL.
   */
  #[\NoDiscard]
  public function generatePresignedUrl(
    string $remotePath,
    int $expiresIn = 3600,
  ): string;

  /**
   * Creates a CloudFront invalidation via REST API.
   *
   * @param string $distributionId
   *   CloudFront distribution ID.
   * @param array<int, string> $paths
   *   Paths to invalidate.
   *
   * @throws \RuntimeException
   *   If the invalidation fails.
   */
  public function createCloudFrontInvalidation(
    string $distributionId,
    array $paths,
  ): void;

}
