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

use Ferienpass\CmsBundle\Menu\MenuBuilder;
use Ferienpass\CmsBundle\UserAccount\UserAccountFragments;
use Ferienpass\CoreBundle\Payments\PaymentSystem;
use Knp\Menu\MenuFactory;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;

final class MenuBuilderTest extends TestCase
{
    // ---- userNavigation ----

    public function testUserNavigationReturnsThreeItems(): void
    {
        $menu = $this->createBuilder()->userNavigation();
        self::assertCount(3, $menu->getChildren());
        self::assertNotNull($menu->getChild('Teilnehmer:innen'));
        self::assertNotNull($menu->getChild('Nutzer-Account'));
        self::assertNotNull($menu->getChild('Abmelden'));
    }

    // ---- userAccountNavigation ----

    public function testUserAccountNavigationSkipsHiddenFragments(): void
    {
        $fragments = new UserAccountFragments();
        $fragments->addFragment('visible', 'visible', 'icon', 'Visible');
        $fragments->addFragment('hidden', 'hidden', 'icon', 'Hidden', hideFromNavigation: true);

        $menu = $this->createBuilder(fragments: $fragments)->userAccountNavigation();

        self::assertCount(1, $menu->getChildren());
        self::assertNotNull($menu->getChild('Visible'));
    }

    public function testUserAccountNavigationSkipsPaymentsWhenDisabled(): void
    {
        $fragments = new UserAccountFragments();
        $fragments->addFragment('payments', 'payments', 'icon', 'Payments');

        $menu = $this->createBuilder(fragments: $fragments, paymentSystem: $this->paymentSystem(false))->userAccountNavigation();
        self::assertCount(0, $menu->getChildren());
    }

    public function testUserAccountNavigationIncludesPaymentsWhenEnabled(): void
    {
        $fragments = new UserAccountFragments();
        $fragments->addFragment('payments', 'payments', 'icon', 'Payments');

        $menu = $this->createBuilder(fragments: $fragments, paymentSystem: $this->paymentSystem(true))->userAccountNavigation();
        self::assertCount(1, $menu->getChildren());
        self::assertNotNull($menu->getChild('Payments'));
    }

    public function testUserAccountNavigationGroupsByAlias(): void
    {
        $fragments = new UserAccountFragments();
        $fragments->addFragment('first', 'same-alias', 'icon', 'First');
        $fragments->addFragment('second', 'same-alias', 'icon', 'Second');

        $menu = $this->createBuilder(fragments: $fragments)->userAccountNavigation();
        // Only one menu child because both share the same alias
        self::assertCount(1, $menu->getChildren());
    }

    public function testUserAccountNavigationUsesLabelOrKeyFallback(): void
    {
        $fragments = new UserAccountFragments();
        $fragments->addFragment('my_key', 'alias1', 'icon'); // no label → key as fallback

        $menu = $this->createBuilder(fragments: $fragments)->userAccountNavigation();
        self::assertNotNull($menu->getChild('my_key'));
    }

    private function createBuilder(
        ?UserAccountFragments $fragments = null,
        ?PaymentSystem $paymentSystem = null,
        ?RequestStack $requestStack = null,
    ): MenuBuilder {
        return new MenuBuilder(
            new MenuFactory(),
            $this->createStub(LogoutUrlGenerator::class),
            $requestStack ?? new RequestStack(),
            $fragments ?? new UserAccountFragments(),
            $paymentSystem ?? $this->paymentSystem(false),
        );
    }

    private function paymentSystem(bool $enabled): PaymentSystem
    {
        $paymentSystem = $this->createStub(PaymentSystem::class);
        $paymentSystem->method('isEnabled')->willReturn($enabled);

        return $paymentSystem;
    }
}
