<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Serenity\CoreBundle\Shared\EventListener;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpKernel\Event\ControllerEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
 * Charge automatiquement une entité Doctrine à partir de la requête
 * et l’ajoute aux attributs sous le nom `entity_instance`.
 *
 * Ce listener s’applique aux routes terminant par `_edit` et dont les
 * paramètres `entity` et `id` sont présents. Il simplifie ainsi la
 * récupération de l’entité correspondante dans le contrôleur.
 *
 * Utile notamment lorsque la route ne possède pas de contrôleur custom,
 * comme dans le cas d’une page rendue par le `TemplateController` de Symfony.
 * Dans ce scénario, le listener injecte l’entité dans la requête pour
 * permettre au template d’y accéder directement sans logique supplémentaire.
 */
final readonly class ResolveEntityFromRequestListener
{
    public function __construct(
        private EntityManagerInterface $em,
    ) {
    }

    #[AsEventListener(event: ControllerEvent::class)]
    public function onKernelController(ControllerEvent $event): void
    {
        $request = $event->getRequest();
        $route = $request->attributes->get('_route');
        $id = $request->attributes->get('id');
        $entityClass = $request->attributes->get('entity');

        // conditions : route doit finir par _edit + avoir un paramètre id + avoir un entity défini
        if (!$route || !$this->isSupportedRoute($route) || !$id || !$entityClass) {
            return;
        }

        $entity = $this->em->getRepository($entityClass)->find($id);
        $request->attributes->set('entity_instance', $entity);

        if (!$entity) {
            throw new NotFoundHttpException(\sprintf('%s with id "%s" not found.', $entityClass, $id));
        }
    }

    private function isSupportedRoute(string $route): bool
    {
        return str_ends_with($route, '_edit')
            || str_ends_with($route, '_view')
            || str_ends_with($route, '_item')
            || str_ends_with($route, '_show');
    }
}
