<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CmsBundle\Tests\DependencyInjection;

use Ferienpass\CmsBundle\Controller\Fragment\OfferDetailsController;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\HttpKernel\HttpKernel;

final class OfferDetailsFragmentRendererTest extends TestCase
{
    private ContainerBuilder $container;

    protected function setUp(): void
    {
        $this->container = new ContainerBuilder();

        // Two parameters that the services.php file references. Set both
        // so the loader doesn't trip on undefined-parameter resolution.
        $this->container->setParameter('kernel.bundles_metadata', []);
        $this->container->setParameter('kernel.debug', false);

        // Stub the HttpKernel class autoload so service definitions that
        // typehint it don't fail compile checks if the loader walks them.
        $this->container->setDefinition(
            HttpKernel::class,
            new \Symfony\Component\DependencyInjection\Definition(HttpKernel::class)->setSynthetic(true),
        );

        $loader = new PhpFileLoader(
            $this->container,
            new FileLocator(\dirname(__DIR__, 2).'/config'),
        );
        $loader->load('services.php');
    }

    public function testOfferDetailsControllerIsRegisteredWithEsiRenderer(): void
    {
        self::assertTrue(
            $this->container->hasDefinition(OfferDetailsController::class),
            'OfferDetailsController must be registered as a service.',
        );

        $tags = $this->container->getDefinition(OfferDetailsController::class)->getTag('ferienpass.fragment');

        self::assertNotEmpty(
            $tags,
            'OfferDetailsController must carry the `ferienpass.fragment` tag — otherwise RegisterFragmentsPass never registers it.',
        );

        $renderers = array_map(static fn (array $attrs): ?string => $attrs['renderer'] ?? null, $tags);

        self::assertContains(
            'esi',
            $renderers,
            \sprintf(
                'OfferDetailsController must be tagged with `renderer: "esi"` so PageBuilder emits an <esi:include> marker '
                .'instead of dispatching it as a sub-request (which breaks the nested render_esi() for the application form). '
                .'Tags found: %s.',
                json_encode($tags),
            ),
        );
    }

    public function testOfferDetailsControllerIsNotTaggedWithDefaultForwardRenderer(): void
    {
        $tags = $this->container->getDefinition(OfferDetailsController::class)->getTag('ferienpass.fragment');

        self::assertCount(
            1,
            $tags,
            \sprintf(
                'OfferDetailsController must have EXACTLY ONE `ferienpass.fragment` tag. '
                .'Found %d. If the prototype load is no longer excluding this file, the default `forward` tag will sneak back in. '
                .'Tags: %s',
                \count($tags),
                json_encode($tags),
            ),
        );

        self::assertSame(
            'esi',
            $tags[0]['renderer'] ?? null,
            'The single `ferienpass.fragment` tag on OfferDetailsController must declare renderer="esi".',
        );
    }
}
