<?php

declare(strict_types=1);

namespace MauticPlugin\DealFlowBundle\EventSubscriber;

use MauticPlugin\DealFlowBundle\Service\LicenseService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;

/**
 * Validates the Deal Flow license on admin page loads.
 * Checks cache first (24hr TTL) to avoid hammering the API.
 * Shows a persistent admin notice when license is invalid.
 */
final class LicenseValidationSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly LicenseService $licenseService,
        private readonly RequestStack $requestStack,
        private readonly AuthorizationCheckerInterface $authChecker,
    ) {
    }

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

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

        $request = $event->getRequest();

        // Skip AJAX requests to avoid consuming flashes in XHR responses
        if ($request->isXmlHttpRequest()) {
            return;
        }

        // Only check on Mautic admin routes
        $route = (string) $request->attributes->get('_route', '');
        if (!str_starts_with($route, 'mautic_')) {
            return;
        }

        // Only for authenticated admins
        try {
            if (!$this->authChecker->isGranted('ROLE_ADMIN')) {
                return;
            }
        } catch (AuthenticationCredentialsNotFoundException) {
            return;
        }

        // Show a notice if installed but not configured (only on config page to avoid noise)
        $status = $this->licenseService->getStatus();
        if ($status === 'not_configured') {
            if (str_starts_with($route, 'mautic_config')) {
                $this->addFlash(
                    'notice',
                    'Deal Flow is installed but not licensed. Enter your license key in the Deal Flow Settings tab.'
                );
            }

            return;
        }

        $result = $this->licenseService->validate();

        // Show warning if license is invalid (but not if API was unreachable with a prior valid state)
        if (!$result->valid && !$result->apiUnreachable) {
            $this->addFlash(
                'warning',
                'Deal Flow license invalid: '.$result->message.'. Visit Plugin Settings to update your key.'
            );

            return;
        }

        // File integrity check disabled — too noisy during frequent updates.
        // The license hash check in isLicensed() is the real enforcement layer.
        // File checksums will be re-enabled in a future release with better
        // auto-recalculation after updates.
    }

    private function addFlash(string $type, string $message): void
    {
        $session = $this->requestStack->getMainRequest()?->getSession();
        if ($session instanceof \Symfony\Component\HttpFoundation\Session\Session) {
            $session->getFlashBag()->add($type, $message);
        }
    }
}
