<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Cdn;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\KeyValueStore\KeyValueFactoryInterface;
use Drupal\Core\State\StateInterface;
use Psr\Log\LoggerInterface;

/**
 * Service for managing CDN integrations.
 *
 * @internal
 */
final class CdnManager implements CdnManagerInterface {

  /**
   * Cached CDN integrations.
   *
   * @var array<string, \Drupal\ffmpeg_media\Cdn\CdnIntegrationInterface>
   */
  protected array $integrations = [];

  /**
   * Constructs a CdnManager object.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $configFactory
   *   Config factory.
   * @param \Drupal\Core\File\FileSystemInterface $fileSystem
   *   File system service.
   * @param \Psr\Log\LoggerInterface $logger
   *   Logger.
   * @param \Drupal\Core\KeyValueStore\KeyValueFactoryInterface $keyValueFactory
   *   Key-value factory.
   * @param \Drupal\Core\State\StateInterface $state
   *   The state service for non-exportable secret storage.
   * @param object|null $keyRepository
   *   Optional Key module repository service.
   */
  public function __construct(
    protected readonly ConfigFactoryInterface $configFactory,
    protected readonly FileSystemInterface $fileSystem,
    protected readonly LoggerInterface $logger,
    protected readonly KeyValueFactoryInterface $keyValueFactory,
    protected readonly StateInterface $state,
    protected readonly ?object $keyRepository = NULL,
  ) {}

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function isEnabled(): bool {
    $config = $this->configFactory->get('ffmpeg_media.cdn');
    $enabled = (bool) ($config->get('enabled') ?? FALSE);

    if (!$enabled) {
      return FALSE;
    }

    $integration = $this->getActiveIntegration();
    return $integration !== NULL && $integration->isConfigured();
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getActiveIntegration(): ?CdnIntegrationInterface {
    $config = $this->configFactory->get('ffmpeg_media.cdn');
    $providerId = $config->get('provider') ?? NULL;

    if ($providerId === NULL) {
      return NULL;
    }

    return $this->getIntegration($providerId);
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getAvailableProviders(): array {
    return [
      's3' => 'S3-Compatible Storage (AWS S3, MinIO, DigitalOcean Spaces, etc.)',
    ];
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getIntegration(string $providerId): ?CdnIntegrationInterface {
    if (isset($this->integrations[$providerId])) {
      return $this->integrations[$providerId];
    }

    if ($this->keyRepository === NULL) {
      $this->logger->debug('Key module not available: key.repository service not injected. CDN credential storage limited to environment variables and State API.');
    }

    $integration = match ($providerId) {
      's3' => new S3CdnIntegration(
        $this->configFactory,
        $this->fileSystem,
        $this->logger,
        $this->keyValueFactory,
        $this->state,
        $this->keyRepository,
      ),
      default => NULL,
    };

    if ($integration !== NULL) {
      $this->integrations[$providerId] = $integration;
    }

    return $integration;
  }

}
