<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media_image\Hook;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Hook\Attribute\Hook;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\ffmpeg_media_image\Service\TemporaryFileAccessManagerInterface;
use Drupal\media\MediaInterface;

/**
 * Hook implementations for private file download access control.
 *
 * Grants download access to temporary private thumbnails and previews by
 * verifying entity-level view access on related media entities.
 */
final class FileDownloadHooks {

  /**
   * URI prefixes managed by this module.
   *
   * @var array<int, string>
   */
  private const array MANAGED_PREFIXES = [
    'private://ffmpeg_media/thumbnails/',
    'private://ffmpeg_media/previews/',
  ];

  /**
   * Constructs a FileDownloadHooks object.
   *
   * @param \Drupal\ffmpeg_media_image\Service\TemporaryFileAccessManagerInterface $temporaryFileAccessManager
   *   Temporary file access manager.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   Entity type manager.
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   *   The current user.
   */
  public function __construct(
    private readonly TemporaryFileAccessManagerInterface $temporaryFileAccessManager,
    private readonly EntityTypeManagerInterface $entityTypeManager,
    private readonly AccountProxyInterface $currentUser,
  ) {}

  /**
   * Implements hook_file_download().
   *
   * Controls access to private thumbnail and preview files generated during
   * poster selection. Access is granted only when the current user can view at
   * least one media entity that registered the temporary URI.
   *
   * @param string $uri
   *   The file URI being requested.
   *
   * @return array<string, string>|int|null
   *   Headers array to allow, -1 to deny, or NULL to abstain.
   */
  #[Hook('file_download')]
  public function fileDownload(string $uri): array|int|null {
    if (!$this->isManagedUri($uri)) {
      return NULL;
    }

    $accessRecord = $this->temporaryFileAccessManager->getAccessRecord($uri);
    if ($accessRecord === NULL) {
      return -1;
    }

    $mediaStorage = $this->entityTypeManager->getStorage('media');
    $mediaEntities = $mediaStorage->loadMultiple($accessRecord['media_ids']);

    foreach ($accessRecord['media_ids'] as $mediaId) {
      $media = $mediaEntities[$mediaId] ?? NULL;
      if ($media instanceof MediaInterface && $media->access('view', $this->currentUser)) {
        return [
          'Content-Type' => $accessRecord['filemime'],
          'Cache-Control' => 'private, max-age=3600',
        ];
      }
    }

    return -1;
  }

  /**
   * Checks whether the URI is managed by this module.
   *
   * @param string $uri
   *   The file URI to check.
   *
   * @return bool
   *   TRUE if this module manages access for this URI.
   */
  private function isManagedUri(string $uri): bool {
    foreach (self::MANAGED_PREFIXES as $prefix) {
      if (str_starts_with($uri, $prefix)) {
        return TRUE;
      }
    }

    return FALSE;
  }

}
