<?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\Seo\Model\Header;
use AutoAdmin\Bundle\Seo\Model\SeoPage;
use AutoAdmin\Bundle\Seo\Renderer\TagRenderer;
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\RequestEvent;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class MainContentRequestSubscriber implements EventSubscriberInterface
{
    private ContentContext $contentContext;
    private EventDispatcherInterface $eventDispatcher;
    private BotDetectorInterface $botDetector;
    private ?TagRenderer $tagRenderer;

    public function __construct(
        ContentContext $contentContext,
        EventDispatcherInterface $eventDispatcher,
        BotDetectorInterface $botDetector,
        ?TagRenderer $tagRenderer
    ) {
        $this->contentContext = $contentContext;
        $this->eventDispatcher = $eventDispatcher;
        $this->botDetector = $botDetector;
        $this->tagRenderer = $tagRenderer;
    }

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

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

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

        // todo, here, use content config to know if we have to handle current route
        if (
            $route === null
            || substr($route, 0, 1) === '_'
            || substr($route, 0, 9) === 'aa_admin_'
        ) {
            return;
        }

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

    public function onKernelResponse(ResponseEvent $event): Response|null
    {
        if (!$event->isMainRequest()) {
            return null;
        }

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

        // todo, here, use content config to know if we have to handle current route
        if (
            $route === null
            || substr($route, 0, 1) === '_'
            || substr($route, 0, 9) === 'aa_admin_'
        ) {
            return null;
        }

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

        // 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();
        $content = $response->getContent();
        if (
            $this->tagRenderer
            && ($seoPage = $this->contentContext->getSeoPage())
            && stripos($content, '<!-- seo -->') !== false
            && stripos($content, '<!-- /seo -->') !== false
        ) {

            $response = $this->addRobotsTagHeader($response, $seoPage);
            $response = $this->replaceSeoTags($response, $seoPage);
        }

        $response->headers->setCookie(Cookie::create(
            'aa_is_bot',
            $this->botDetector->isBotRequest(),
            0,
            '/',
            null,
            false,
            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
     */
    private function addRobotsTagHeader(Response $response, ?SeoPage $seoPage): Response
    {
        if ($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;
    }

    private function replaceSeoTags(Response $response, SeoPage $seoPage): Response
    {
        $content = preg_replace_callback(
            '/(<!-- seo -->)(.+?)(<!-- \/seo -->)/msu',
            function ($matches) use ($seoPage) {
                if (is_array($matches)) {
                    $matches[2] = $this->tagRenderer->render($seoPage);
                    $matches = implode('', array_slice($matches, 1));

                    return $matches;
                }

                return $matches;
            },
            $response->getContent()
        );
        $response->setContent($content);

        return $response;
    }
}
