<?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\Routing;

use Contao\CoreBundle\Routing\ContentUrlGenerator;
use Ferienpass\CmsBundle\Routing\LocaleContentUrlGeneratorDecorator;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\RequestContext;

class LocaleContentUrlGeneratorDecoratorTest extends TestCase
{
    #[DataProvider('generateProvider')]
    public function testGenerate(string $locale, string $innerUrl, string $expectedUrl): void
    {
        $inner = $this->createMock(ContentUrlGenerator::class);
        $requestStack = new RequestStack();
        if ('' !== $locale) {
            $request = new Request([], [], ['_locale' => $locale]);
            $requestStack->push($request);
        }

        $decorator = new LocaleContentUrlGeneratorDecorator(
            $inner,
            $requestStack
        );

        $content = new \stdClass();
        $inner->expects($this->once())
            ->method('generate')
            ->willReturn($innerUrl);

        $this->assertSame($expectedUrl, $decorator->generate($content));
    }

    public static function generateProvider(): array
    {
        return [
            'No locale' => [
                '',
                '/some-page.html',
                '/some-page.html',
            ],
            'Locale ru' => [
                'ru',
                '/some-page.html',
                '/ru/some-page.html',
            ],
            'Locale en' => [
                'en',
                '/some-page.html',
                '/en/some-page.html',
            ],
            'Locale de (empty prefix)' => [
                'de',
                '/some-page.html',
                '/some-page.html',
            ],
            'Already prefixed ru' => [
                'ru',
                '/ru/some-page.html',
                '/ru/some-page.html',
            ],
            'Already prefixed en while locale is ru' => [
                'ru',
                '/en/some-page.html',
                '/ru/en/some-page.html', // This is what the current implementation does
            ],
            'Absolute URL' => [
                'ru',
                'https://example.com/some-page.html',
                'https://example.com/some-page.html',
            ],
            'Index page' => [
                'ru',
                '/',
                '/ru/',
            ],
        ];
    }

    public function testSetContextDelegatesToInner(): void
    {
        $inner = $this->createMock(ContentUrlGenerator::class);
        $requestStack = new RequestStack();
        $decorator = new LocaleContentUrlGeneratorDecorator($inner, $requestStack);
        $context = new RequestContext();

        $inner->expects($this->once())->method('setContext')->with($context);

        $decorator->setContext($context);
    }

    public function testGetContextDelegatesToInner(): void
    {
        $inner = $this->createMock(ContentUrlGenerator::class);
        $requestStack = new RequestStack();
        $decorator = new LocaleContentUrlGeneratorDecorator($inner, $requestStack);
        $context = new RequestContext();

        $inner->expects($this->once())->method('getContext')->willReturn($context);

        self::assertSame($context, $decorator->getContext());
    }

    public function testResetDelegatesToInner(): void
    {
        $inner = $this->createMock(ContentUrlGenerator::class);
        $requestStack = new RequestStack();
        $decorator = new LocaleContentUrlGeneratorDecorator($inner, $requestStack);

        $inner->expects($this->once())->method('reset');

        $decorator->reset();
    }
}
