<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\EventSubscriber;

use MauticPlugin\DealFlowBundle\Service\LicenseService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;

/**
 * Blocks access to all Deal Flow routes when the license is not active.
 *
 * Allowed without a license:
 * - Config/settings routes (so the user can enter a key)
 * - Public webhook routes (don't break existing integrations)
 */
final class LicenseRouteGuard implements EventSubscriberInterface
{
    /** @var list<string> Routes that are always allowed (config + public webhooks). */
    private const ALLOWED_ROUTE_PREFIXES = [
        'mautic_config',
        'mautic_public_dealflow_webhook',
    ];

    public function __construct(
        private readonly LicenseService $licenseService,
        private readonly RouterInterface $router,
    ) {
    }

    /**
     * @return array<string, array<int, int|string>>
     */
    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => ['onKernelRequest', 0],
        ];
    }

    public function onKernelRequest(RequestEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }

        $request = $event->getRequest();
        $route = (string) $request->attributes->get('_route', '');

        // Only intercept Deal Flow routes
        if (!$this->isDealFlowRoute($route)) {
            return;
        }

        // Always allow config and public webhook routes
        if ($this->isAllowedRoute($route)) {
            return;
        }

        // If licensed (status + integrity hash verified), let the request through
        if ($this->licenseService->isLicensed()) {
            return;
        }

        // Not licensed — block the request
        if ($this->isApiRoute($route)) {
            $event->setResponse(new JsonResponse(
                ['error' => 'Deal Flow is not licensed. Enter your license key in Mautic Configuration.'],
                Response::HTTP_FORBIDDEN
            ));

            return;
        }

        // For main (browser) routes, redirect to config page with flash
        $session = $request->getSession();
        if ($session instanceof \Symfony\Component\HttpFoundation\Session\Session) {
            $session->getFlashBag()->add(
                'warning',
                'Deal Flow is not licensed. Enter your license key in Configuration > Deal Flow Settings.'
            );
        }

        $event->setResponse(new RedirectResponse(
            $this->router->generate('mautic_config_action', ['objectAction' => 'edit'])
        ));
    }

    private function isDealFlowRoute(string $route): bool
    {
        return str_starts_with($route, 'mautic_dealflow_')
            || str_starts_with($route, 'mautic_api_dealflow_')
            || str_starts_with($route, 'mautic_public_dealflow_');
    }

    private function isAllowedRoute(string $route): bool
    {
        foreach (self::ALLOWED_ROUTE_PREFIXES as $prefix) {
            if (str_starts_with($route, $prefix)) {
                return true;
            }
        }

        return false;
    }

    private function isApiRoute(string $route): bool
    {
        return str_starts_with($route, 'mautic_api_dealflow_');
    }
}
