<?php

declare(strict_types=1);

namespace Drupal\nodehive_path_alias\EventSubscriber;

use Drupal\decoupled_router\PathTranslatorEvent;
use Drupal\nodehive_path_alias\PathAliasSpaceLookupInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

use function sprintf;

/**
 * Resolves path aliases by explicit ?space_id= query parameter.
 *
 * Priority 100 — runs before the core RouterPathTranslatorSubscriber (0) and
 * before the API token subscriber (90).
 *
 * Frontend usage:
 *   GET /router/translate-path?path=/about&space_id=1
 *   GET /router/translate-path?path=/about&space_id=1&langcode=cs
 *
 * The space_id matches NEXT_PUBLIC_DRUPAL_NODEHIVE_SPACE_ID in the Next.js env.
 */
final class SpaceIdPathTranslatorSubscriber implements EventSubscriberInterface {

  public function __construct(
    private readonly PathAliasSpaceLookupInterface $lookup,
  ) {}

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      PathTranslatorEvent::TRANSLATE => ['onPathTranslation', 100],
    ];
  }

  /**
   * Resolves the path translation using the space_id query parameter.
   */
  public function onPathTranslation(PathTranslatorEvent $event): void {
    $request = $event->getRequest();
    $rawSpaceId = $request->query->get('space_id');
    if ($rawSpaceId === NULL || $rawSpaceId === '') {
      return;
    }

    $spaceId = (int) $rawSpaceId;
    if ($spaceId <= 0) {
      return;
    }

    $alias = $this->cleanAlias($event->getPath(), $request->getBasePath());
    $langcode = $request->query->get('langcode') ?: NULL;

    $systemPath = $this->lookup->resolve($alias, $spaceId, $langcode);
    if ($systemPath === NULL) {
      return;
    }

    $event->setPath($systemPath);
    $request->attributes->set('_nodehive_space_resolved', TRUE);
    $event->getResponse()
      ->getCacheableMetadata()
      ->addCacheContexts(['url.query_args:space_id', 'url.query_args:langcode']);
  }

  /**
   * Strips the base path prefix from a path alias string.
   */
  private function cleanAlias(string $path, string $basePath): string {
    if ($basePath === '') {
      return $path;
    }

    return preg_replace(sprintf('/^%s/', preg_quote($basePath, '/')), '', $path);
  }

}
