<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media_ui\Access;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\ffmpeg_media\Service\FormatterSettingsResolverInterface;
use Drupal\media\MediaInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Route access callback for transcode-related UI tools.
 *
 * Accepts the dedicated UI permission as well as the existing core
 * convert/reconvert permissions for backward-compatible role setups.
 */
final class MediaTranscodeAccess implements ContainerInjectionInterface {

  /**
   * Transcode-capable permissions accepted by the UI routes.
   *
   * @var array<int, string>
   */
  private const array TRANSCODE_PERMISSIONS = [
    'transcode media',
    'convert media',
    'reconvert media',
  ];

  /**
   * Constructs a MediaTranscodeAccess object.
   *
   * @param \Drupal\ffmpeg_media\Service\FormatterSettingsResolverInterface $formatterSettingsResolver
   *   Formatter settings resolver service.
   */
  public function __construct(
    private readonly FormatterSettingsResolverInterface $formatterSettingsResolver,
  ) {}

  /**
   * {@inheritdoc}
   */
  #[\Override]
  public static function create(ContainerInterface $container): static {
    return new static(
      $container->get(FormatterSettingsResolverInterface::class),
    );
  }

  /**
   * Grants access for mapped media transcode routes.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media route parameter.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Account performing the request.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   Access decision with cacheability metadata.
   */
  public function access(MediaInterface $media, AccountInterface $account): AccessResult {
    $mappingAccess = AccessResult::allowedIf($this->formatterSettingsResolver->getContextsForEntity($media) !== [])
      ->addCacheableDependency($media)
      ->addCacheTags(['config:core.entity_view_display.media.' . $media->bundle() . '.default']);

    return $mappingAccess
      ->andIf($this->buildPermissionAccess($account))
      ->andIf($media->access('update', $account, TRUE));
  }

  /**
   * Grants access for thumbnail generation without requiring formatter mapping.
   *
   * @param \Drupal\media\MediaInterface $media
   *   The media route parameter.
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Account performing the request.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   Access decision with cacheability metadata.
   */
  public function thumbnailAccess(MediaInterface $media, AccountInterface $account): AccessResult {
    return $this->buildPermissionAccess($account)
      ->andIf($media->access('update', $account, TRUE));
  }

  /**
   * Builds the permission access result shared by transcode UI routes.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Account performing the request.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   Permission access result with cacheability metadata.
   */
  private function buildPermissionAccess(AccountInterface $account): AccessResult {
    return AccessResult::allowedIfHasPermissions(
      $account,
      self::TRANSCODE_PERMISSIONS,
      'OR',
    );
  }

}
