<?php

namespace AutoAdmin\Bundle\Content\EventListener;

use AutoAdmin\Bundle\Content\Context\ContentContext;
use AutoAdmin\Bundle\Content\Event\ContentEvents;
use AutoAdmin\Bundle\Content\Event\ContentMatchEvent;
use AutoAdmin\Bundle\Content\Event\ContentMetadataEvent;
use AutoAdmin\Bundle\Content\Event\PostContentMetadataEvent;
use AutoAdmin\Bundle\Content\Frontend\FrontendUrlChecker;
use AutoAdmin\Bundle\Seo\Model\Header;
use AutoAdmin\Bundle\Seo\Model\SeoPage;
use AutoAdmin\Bundle\Seo\Renderer\RendererManager;
use Setono\BotDetectionBundle\BotDetector\BotDetectorInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\KernelEvent;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class MainContentRequestSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly ContentContext $contentContext,
        private readonly EventDispatcherInterface $eventDispatcher,
        private readonly BotDetectorInterface $botDetector,
        private readonly RendererManager $rendererManager,
        private readonly FrontendUrlChecker $frontendUrlChecker,
    ) {
    }

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

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

        // ContentEvents::MATCH
        $this->eventDispatcher->dispatch(
            new ContentMatchEvent($this->contentContext, $event->getRequest()),
            ContentEvents::MATCH
        );
    }

    protected function isSupportedRequest(KernelEvent $event): bool
    {
        return $event->isMainRequest() && $this->frontendUrlChecker->isFrontUrl($event->getRequest());
    }

    public function onKernelResponse(ResponseEvent $event): ?Response
    {
        if (!$this->isSupportedRequest($event)) {
            return $event->getResponse();
        }

        $request = $event->getRequest();

        // ContentEvents::METADATA
        $this->eventDispatcher->dispatch(
            new ContentMetadataEvent($this->contentContext, $request),
            ContentEvents::METADATA
        );

        // ContentEvents::POST_METADATA
        $this->eventDispatcher->dispatch(
            new PostContentMetadataEvent($this->contentContext, $request),
            ContentEvents::POST_METADATA
        );

        $response = $event->getResponse();
        if ($seoPage = $this->contentContext->getSeoPage()) {
            foreach ($this->rendererManager->getRenderers() as $renderer) {
                $response = $renderer->render($response, $seoPage);
            }
            $response = $this->addRobotsTagHeader($response, $seoPage);
        }

        $response->headers->setCookie(
            Cookie::create(
                name: 'aa_is_bot',
                value: $this->botDetector->isBotRequest(),
                secure: false,
                httpOnly: false,
            )
        );

        return $response;
    }

    /*
     * Beware, if we do not create X-Robots-Tag here,
     * \Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener will create a noindex rule for "DEV" env
     */
    protected function addRobotsTagHeader(Response $response, ?SeoPage $seoPage): Response
    {
        if ($seoPage && $seoPage->getResponseHeaders()) {
            /** @var Header $header */
            foreach ($seoPage->getResponseHeaders() as $header) {
                if (!$response->headers->has($header->getName())) {
                    $response->headers->set($header->getName(), $header->getValue());
                }
            }
        }

        return $response;
    }
}
