<?php

declare(strict_types=1);

namespace Ferienpass\AdminBundle\Tests\Routing;

use Ferienpass\AdminBundle\Routing\Base58AdminRouter;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Uid\Uuid;

final class Base58AdminRouterTest extends TestCase
{
    private const RFC = '6d4bcd4f-bc7a-4ba7-bb60-700b515bab4b';

    private function decorator(RouterInterface $inner): Base58AdminRouter
    {
        return new Base58AdminRouter($inner);
    }

    /**
     * @return array{0: RouterInterface, 1: \stdClass}
     */
    private function capturingInner(): array
    {
        $captured = new \stdClass();
        $captured->params = null;
        $inner = $this->createMock(RouterInterface::class);
        $inner->method('generate')->willReturnCallback(
            static function (string $name, array $parameters = [], int $type = UrlGeneratorInterface::ABSOLUTE_PATH) use ($captured): string {
                $captured->params = $parameters;

                return '/generated';
            }
        );

        return [$inner, $captured];
    }

    public function testAdminRouteEncodesUuidObjectToBase58(): void
    {
        $uuid = Uuid::fromString(self::RFC);
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('admin_offers_show', ['uuid' => $uuid]);

        self::assertSame($uuid->toBase58(), $captured->params['uuid']);
    }

    public function testAdminRouteEncodesRfc4122StringToBase58(): void
    {
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('admin_offers_show', ['uuid' => self::RFC]);

        self::assertSame(Uuid::fromString(self::RFC)->toBase58(), $captured->params['uuid']);
    }

    public function testEncodesUuid1AndUuid2(): void
    {
        $a = Uuid::v7();
        $b = Uuid::v7();
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('admin_participant_duplicates_merge_modal', ['uuid1' => $a, 'uuid2' => $b]);

        self::assertSame($a->toBase58(), $captured->params['uuid1']);
        self::assertSame($b->toBase58(), $captured->params['uuid2']);
    }

    public function testLegacyAdminRouteIsLeftUntouched(): void
    {
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('admin_offers_show_legacy', ['uuid' => self::RFC]);

        self::assertSame(self::RFC, $captured->params['uuid']);
    }

    public function testNonAdminRouteIsLeftUntouched(): void
    {
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('cms_offer_private_link', ['uuid' => self::RFC]);

        self::assertSame(self::RFC, $captured->params['uuid']);
    }

    public function testAlreadyBase58IsIdempotent(): void
    {
        $base58 = Uuid::fromString(self::RFC)->toBase58();
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('admin_offers_show', ['uuid' => $base58]);

        self::assertSame($base58, $captured->params['uuid']);
    }

    public function testNonUuidValue_LikeLegacyConsentIntegerId_IsLeftUntouched(): void
    {
        [$inner, $captured] = $this->capturingInner();

        $this->decorator($inner)->generate('admin_consents_show', ['uuid' => '42']);

        self::assertSame('42', $captured->params['uuid']);
    }
}
