<?php

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\RateLimiter\RateLimiterFactory;

class RateLimiterSubscriber implements EventSubscriberInterface
{
    private const ROUTE_LIMITER_MAP = [
        'app_order_create' => 'order_create',
        'app_invitation_respond' => 'invitation_respond',
        'app_invitation_register' => 'invitation_respond',
        'app_event_contact' => 'contact_form',
        'app_contact' => 'contact_form',
        'app_order_public' => 'order_public',
    ];

    /**
     * @param array<string, RateLimiterFactory> $limiters
     */
    public function __construct(
        private readonly array $limiters,
        #[\Symfony\Component\DependencyInjection\Attribute\Autowire('%kernel.environment%')] private readonly string $env = 'prod',
    ) {
    }

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => ['onKernelRequest', 10],
        ];
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        if (!$event->isMainRequest() || 'test' === $this->env) {
            return;
        }

        $request = $event->getRequest();
        $route = $request->attributes->getString('_route');

        if (!isset(self::ROUTE_LIMITER_MAP[$route])) {
            return;
        }

        $limiterName = self::ROUTE_LIMITER_MAP[$route];
        if (!isset($this->limiters[$limiterName])) {
            return;
        }

        $limiter = $this->limiters[$limiterName]->create($request->getClientIp() ?? 'unknown');
        $limit = $limiter->consume();

        if (!$limit->isAccepted()) {
            $event->setResponse(new Response('Trop de requetes. Reessayez plus tard.', 429));
        }
    }
}
