<?php

declare(strict_types=1);

namespace App\EventSubscriber;

use App\Service\LicenseEnforcementService;
use App\Service\TenantContext;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Twig\Environment;

/**
 * Enforces license limits on POST requests and blocks access
 * when license is fully expired (past grace period).
 *
 * Priority 5 — runs after TenantSubscriber (255) and ModuleGuard (10),
 * but still before controller.
 */
class LicenseEnforcementSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly TenantContext $tenantContext,
        private readonly LicenseEnforcementService $enforcementService,
        private readonly Environment $twig,
    ) {}

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

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

        // Only enforce when we have a resolved tenant
        if (!$this->tenantContext->isResolved()) {
            return;
        }

        $request = $event->getRequest();
        $path = $request->getPathInfo();

        // Skip enforcement for central panel
        if (str_starts_with($path, '/central')) {
            return;
        }

        // Skip profiler and assets
        if (str_starts_with($path, '/_') || str_starts_with($path, '/build')) {
            return;
        }

        // Check if license is fully expired (past grace period)
        if ($this->enforcementService->isFullyExpired()) {
            $event->setResponse(new Response(
                $this->renderErrorPage('error/license_expired.html.twig'),
                403
            ));
            return;
        }

        // For grace period: allow GET (read-only) but block POST (modifications)
        if ($this->enforcementService->isInGracePeriod() && $request->isMethod('POST')) {
            // Allow login/logout during grace period
            if (str_contains($path, '/login') || str_contains($path, '/logout')) {
                return;
            }

            $this->addFlashAndRedirect($event, 'Lisansınız süresi dolmuş. Grace period içindesiniz — yeni içerik ekleyemezsiniz.');
            return;
        }

        // Enforce limits on POST requests only (creating/editing content)
        if (!$request->isMethod('POST')) {
            return;
        }

        // Check specific limits based on route
        $route = $request->attributes->get('_route', '');

        // User creation limit
        if (in_array($route, ['admin_user_create', 'admin_user_new'], true)) {
            $result = $this->enforcementService->checkUserLimit();
            if (!$result->allowed) {
                $this->addFlashAndRedirect($event, $result->message);
                return;
            }
        }

        // News creation limit
        if (in_array($route, ['admin_news_create', 'admin_news_new'], true)) {
            $result = $this->enforcementService->checkNewsLimit();
            if (!$result->allowed) {
                $this->addFlashAndRedirect($event, $result->message);
                return;
            }
        }

        // Media upload / storage limit
        if (in_array($route, ['admin_media_upload', 'admin_media_create'], true)) {
            $result = $this->enforcementService->checkStorageLimit();
            if (!$result->allowed) {
                $this->addFlashAndRedirect($event, $result->message);
                return;
            }
        }
    }

    private function addFlashAndRedirect(RequestEvent $event, string $message): void
    {
        $request = $event->getRequest();
        $session = $request->getSession();

        if ($session) {
            $session->getFlashBag()->add('error', $message);
        }

        $referer = $request->headers->get('referer', '/admin');
        $event->setResponse(new RedirectResponse($referer));
    }

    private function renderErrorPage(string $template): string
    {
        try {
            return $this->twig->render($template);
        } catch (\Exception) {
            return '<html><body><h1>Lisans Süresi Doldu</h1><p>Lisansınızı yenilemek için yöneticinizle iletişime geçin.</p></body></html>';
        }
    }
}
