<?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\CoreBundle\Tests\Tenant;

use Contao\Model\Collection;
use Contao\PageModel;
use Contao\TestCase\ContaoTestCase;
use Doctrine\DBAL\Connection;
use Ferienpass\CoreBundle\Entity\Tenant;
use Ferienpass\CoreBundle\Tenant\TenantContext;
use Ferienpass\CoreBundle\Tenant\TenantRootPage;

class TenantRootPageTest extends ContaoTestCase
{
    /**
     * The whole point: `findPublishedRootPages()[0]` would hand back Lingen's
     * website while serving Nordhorn's data.
     */
    public function testPicksTheRootPageOfTheActiveTenant(): void
    {
        $lingen = $this->rootPage(2);
        $nordhorn = $this->rootPage(1);

        $rootPage = $this->tenantRootPage([$lingen, $nordhorn], $this->tenant(1))->current();

        $this->assertSame($nordhorn, $rootPage);
    }

    public function testReturnsNullWhenTheTenantHasNoRootPageYet(): void
    {
        $this->assertNull($this->tenantRootPage([$this->rootPage(2)], $this->tenant(1))->current());
    }

    /**
     * With no tenant resolved there is no root page to serve — never another
     * municipality's.
     */
    public function testReturnsNullWithoutAnActiveTenant(): void
    {
        $this->assertNull($this->tenantRootPage([$this->rootPage(2)], null)->current());
    }

    /**
     * Single-tenant builds keep the behaviour they had before tenants existed.
     */
    public function testFallsBackToTheFirstRootPageOnASingleTenantBuild(): void
    {
        $first = $this->rootPage(0);

        $rootPage = $this->tenantRootPage([$first, $this->rootPage(0)], null, enabled: false)->current();

        $this->assertSame($first, $rootPage);
    }

    /**
     * @param list<PageModel> $rootPages
     */
    private function tenantRootPage(array $rootPages, ?Tenant $tenant, bool $enabled = true): TenantRootPage
    {
        $framework = $this->createContaoFrameworkStub([
            PageModel::class => $this->createConfiguredAdapterStub([
                'findPublishedRootPages' => new Collection($rootPages, 'tl_page'),
            ]),
        ]);

        $context = $this->createMock(TenantContext::class);
        $context->method('isEnabled')->willReturn($enabled);
        $context->method('getTenant')->willReturn($tenant);

        return new TenantRootPage($framework, $this->createMock(Connection::class), $context);
    }

    private function rootPage(int $tenantId): PageModel
    {
        return $this->createClassWithPropertiesStub(PageModel::class, ['tenant' => $tenantId]);
    }

    private function tenant(int $id): Tenant
    {
        $tenant = new Tenant();
        new \ReflectionProperty(Tenant::class, 'id')->setValue($tenant, $id);

        return $tenant;
    }
}
