<?php

declare(strict_types=1);

/*
 * This file is part of the VITICORE2 package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace CpCreation\VitiCore\Bridge\Symfony\Bundle\EventListener;

use CpCreation\VitiCore\Bridge\Symfony\Bundle\Twig\FileExtension;
use CpCreation\VitiCore\Contact\ContactProvider;
use CpCreation\VitiCore\Seo\LocalBusinessSchemaBuilder;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

final readonly class LocalBusinessStructuredDataSubscriber implements EventSubscriberInterface
{
    private const SCRIPT_ID = 'viti-local-business-schema';

    public function __construct(
        private ContactProvider $contactProvider,
        private LocalBusinessSchemaBuilder $schemaBuilder,
        private FileExtension $fileExtension,
    ) {}

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

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

        $request = $event->getRequest();
        $response = $event->getResponse();
        $route = $request->attributes->getString('_route');
        $contentType = (string) $response->headers->get('Content-Type');

        if (str_starts_with($route, 'admin_') || !str_contains($contentType, 'text/html')) {
            return;
        }

        $content = $response->getContent();
        if (false === $content || str_contains($content, 'id="' . self::SCRIPT_ID . '"')) {
            return;
        }

        $headEndPosition = strripos($content, '</head>');
        if (false === $headEndPosition) {
            return;
        }

        $contact = $this->contactProvider->getContact();
        if (null === $contact) {
            return;
        }

        $businessUrl = rtrim($request->getSchemeAndHttpHost() . $request->getBaseUrl(), '/') . '/';
        $logoUrl = null;

        if (null !== $path = $contact->getImage()?->getPath()) {
            $logoUrl = $request->getUriForPath($this->fileExtension->imagePathFilter($path));
        }

        $schema = $this->schemaBuilder->build($contact, $businessUrl, $logoUrl);
        if (null === $schema) {
            return;
        }

        $json = json_encode(
            $schema,
            \JSON_HEX_TAG | \JSON_HEX_AMP | \JSON_HEX_APOS | \JSON_HEX_QUOT | \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE | \JSON_THROW_ON_ERROR,
        );
        $script = \sprintf(
            "    <script id=\"%s\" type=\"application/ld+json\">%s</script>\n",
            self::SCRIPT_ID,
            $json,
        );

        $response->setContent(substr_replace($content, $script, $headEndPosition, 0));
        $response->headers->remove('Content-Length');
    }
}
