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

use Doctrine\Common\Collections\ArrayCollection;
use Ferienpass\CoreBundle\DataAccess\HostDataAccess;
use Ferienpass\CoreBundle\Entity\Edition;
use Ferienpass\CoreBundle\Entity\EditionTask;
use Ferienpass\CoreBundle\Entity\Offer\OfferInterface;
use Ferienpass\CoreBundle\Entity\PageConfig;
use Ferienpass\CoreBundle\Settings\PageConfigManager;
use PHPUnit\Framework\TestCase;

class HostDataAccessTest extends TestCase
{
    public function testPrefersPublishListsTaskEnd(): void
    {
        $end = new \DateTimeImmutable('2026-09-30 23:59:59');

        $task = $this->createStub(EditionTask::class);
        $task->method('getType')->willReturn('publish_lists');
        $task->method('getPeriodEnd')->willReturn($end);

        $edition = $this->createStub(Edition::class);
        $edition->method('getTasksOfType')->willReturn(new ArrayCollection([$task]));

        $offer = $this->createStub(OfferInterface::class);
        $offer->method('getEdition')->willReturn($edition);
        $offer->method('getDateEnd')->willReturn(new \DateTimeImmutable('2026-07-18'));

        self::assertSame('2026-09-30 23:59:59', $this->hostDataAccess(null)->accessEndDate($offer)->format('Y-m-d H:i:s'));
    }

    public function testFallsBackToOfferEndPlusDefaultSixMonths(): void
    {
        $edition = $this->createStub(Edition::class);
        $edition->method('getTasksOfType')->willReturn(new ArrayCollection());

        $offer = $this->createStub(OfferInterface::class);
        $offer->method('getEdition')->willReturn($edition);
        $offer->method('getDateEnd')->willReturn(new \DateTimeImmutable('2026-07-18'));

        self::assertSame(
            '2027-01-18 00:00:00',
            $this->hostDataAccess(null)->accessEndDate($offer)->format('Y-m-d H:i:s')
        );
    }

    public function testFallbackHonoursConfiguredRetentionPeriod(): void
    {
        $edition = $this->createStub(Edition::class);
        $edition->method('getTasksOfType')->willReturn(new ArrayCollection());

        $offer = $this->createStub(OfferInterface::class);
        $offer->method('getEdition')->willReturn($edition);
        $offer->method('getDateEnd')->willReturn(new \DateTimeImmutable('2026-07-18'));

        self::assertSame(
            '2026-08-01 00:00:00',
            $this->hostDataAccess('14 days')->accessEndDate($offer)->format('Y-m-d H:i:s')
        );
    }

    public function testNoEndDateWhenOfferHasNoEndAndNoTask(): void
    {
        $edition = $this->createStub(Edition::class);
        $edition->method('getTasksOfType')->willReturn(new ArrayCollection());

        $offer = $this->createStub(OfferInterface::class);
        $offer->method('getEdition')->willReturn($edition);
        $offer->method('getDateEnd')->willReturn(null);

        $access = $this->hostDataAccess(null);
        self::assertNull($access->accessEndDate($offer));
        // Unknown end date must not lock the host out.
        self::assertTrue($access->hasAccess($offer));
    }

    public function testHasAccessReflectsCutoff(): void
    {
        $edition = $this->createStub(Edition::class);
        $edition->method('getTasksOfType')->willReturn(new ArrayCollection());

        $offer = $this->createStub(OfferInterface::class);
        $offer->method('getEdition')->willReturn($edition);
        $offer->method('getDateEnd')->willReturn(new \DateTimeImmutable('2026-07-18'));

        $access = $this->hostDataAccess('6 months'); // cutoff 2027-01-18

        self::assertTrue($access->hasAccess($offer, new \DateTimeImmutable('2026-12-31')));
        self::assertFalse($access->hasAccess($offer, new \DateTimeImmutable('2027-02-01')));
    }

    private function hostDataAccess(?string $retentionPeriod): HostDataAccess
    {
        $config = new PageConfig();
        $config->setHostDataRetentionPeriod($retentionPeriod);

        $manager = $this->createStub(PageConfigManager::class);
        $manager->method('getPageConfig')->willReturn($config);

        return new HostDataAccess($manager);
    }
}
