<?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\AdminBundle\Tests\Twig;

use Ferienpass\AdminBundle\Twig\MenuExtension;
use Ferienpass\CoreBundle\Entity\Host;
use Ferienpass\CoreBundle\Entity\Offer\OfferInterface;
use Knp\Menu\ItemInterface;
use Knp\Menu\Twig\Helper;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

final class MenuExtensionTest extends TestCase
{
    public function testGetDelegatesToHelper(): void
    {
        $item = new \stdClass();
        $menuItem = $this->createMock(ItemInterface::class);

        $helper = $this->createMock(Helper::class);
        $helper->expects(self::once())
            ->method('get')
            ->with('admin_list_actions', [], ['item' => $item])
            ->willReturn($menuItem);

        $extension = new MenuExtension($helper, $this->createStub(UrlGeneratorInterface::class));
        $result = $extension->get($item);

        self::assertSame($menuItem, $result);
    }

    public function testGetPassesOptionsToHelper(): void
    {
        $item = new \stdClass();
        $menuItem = $this->createMock(ItemInterface::class);

        $helper = $this->createMock(Helper::class);
        $helper->expects(self::once())
            ->method('get')
            ->with('admin_list_actions', ['sub'], ['item' => $item, 'extra' => 'val'])
            ->willReturn($menuItem);

        $extension = new MenuExtension($helper, $this->createStub(UrlGeneratorInterface::class));
        $result = $extension->get($item, ['sub'], ['extra' => 'val']);

        self::assertSame($menuItem, $result);
    }

    public function testSrcAddressesTheItemByTypeAndId(): void
    {
        $offer = $this->createStub(OfferInterface::class);
        $offer->method('getId')->willReturn(42);

        $urlGenerator = $this->createMock(UrlGeneratorInterface::class);
        $urlGenerator->expects(self::once())
            ->method('generate')
            ->with('admin_list_actions', ['type' => 'offer', 'id' => 42, 'view' => 'admin_offers_index'])
            ->willReturn('/admin/_list-actions/offer/42?view=admin_offers_index');

        $extension = new MenuExtension($this->createStub(Helper::class), $urlGenerator);

        self::assertSame(
            '/admin/_list-actions/offer/42?view=admin_offers_index',
            $extension->src($offer, ['view' => 'admin_offers_index', 'edition' => null]),
        );
    }

    /**
     * A row the endpoint cannot address has to keep the eager menu, or its
     * actions would silently disappear.
     */
    public function testSrcIsNullForAnUnknownType(): void
    {
        $urlGenerator = $this->createMock(UrlGeneratorInterface::class);
        $urlGenerator->expects(self::never())->method('generate');

        $extension = new MenuExtension($this->createStub(Helper::class), $urlGenerator);

        self::assertNull($extension->src(new \stdClass()));
        self::assertNull($extension->src(['not', 'an', 'object']));
    }

    public function testSrcIsNullForAnUnpersistedItem(): void
    {
        $host = $this->createStub(Host::class);
        $host->method('getId')->willReturn(null);

        $urlGenerator = $this->createMock(UrlGeneratorInterface::class);
        $urlGenerator->expects(self::never())->method('generate');

        $extension = new MenuExtension($this->createStub(Helper::class), $urlGenerator);

        self::assertNull($extension->src($host));
    }

    public function testFrameIdMatchesTheOneTheFragmentRenders(): void
    {
        $host = $this->createStub(Host::class);
        $host->method('getId')->willReturn(7);

        $extension = new MenuExtension($this->createStub(Helper::class), $this->createStub(UrlGeneratorInterface::class));

        self::assertSame('list-actions-host-7', $extension->frame($host));
        self::assertNull($extension->frame(new \stdClass()));
    }
}
