<?php

namespace Drupal\acquia_dam\Service;

use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Url;
use Drupal\file\Entity\File;

/**
 * Decorates the file_url_generator to append changed timestamp for DAM assets.
 */
class LocalFileUrlGenerator implements FileUrlGeneratorInterface {

  /**
   * The decorated service.
   */
  protected $innerService;

  /**
   * The entity type manager.
   */
  protected $entityTypeManager;

  /**
   * Static cache for file timestamps to optimize performance.
   */
  protected static $timestamps = [];

  public function __construct(FileUrlGeneratorInterface $inner_service, EntityTypeManagerInterface $entity_type_manager) {
    $this->innerService = $inner_service;
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * Handles cases where a full Url object is requested (like File Links).
   */
  public function generate($uri): Url {
    $url = $this->innerService->generate($uri);

    // We use '://dam/' to catch 'public://dam/', 'private://dam/' schemes.
    if (is_string($uri) && str_contains($uri, '://dam/')) {
      $timestamp = $this->getFileTimestamp($uri);
      if ($timestamp) {
        $options = $url->getOptions();
        $options['query']['changed'] = $timestamp;
        $url->setOptions($options);
      }
    }

    return $url;
  }

  /**
   * Loads the file timestamp, using a static cache to avoid DB hits.
   */
  protected function getFileTimestamp($uri) {
    if (!isset(static::$timestamps[$uri])) {
      $files = $this->entityTypeManager->getStorage('file')
        ->loadByProperties(['uri' => $uri]);

      $file = reset($files);
      static::$timestamps[$uri] = $file instanceof File ? $file->getChangedTime() : FALSE;
    }

    return static::$timestamps[$uri];
  }

  // Delegate all other required interface methods to the inner service.
  public function generateString($uri): string { return $this->innerService->generateString($uri); }
  public function generateAbsoluteString($uri): string { return $this->innerService->generateAbsoluteString($uri); }
  public function transformRelative($file_url, bool $root_relative = true): string { return $this->innerService->transformRelative($file_url); }
}
