<?php

declare(strict_types=1);

namespace Ferienpass\CoreBundle\Tests\ApplicationSystem;

use Ferienpass\CoreBundle\ApplicationSystem\FirstComeApplicationSystem;
use Ferienpass\CoreBundle\ApplicationSystem\LotApplicationSystem;
use Ferienpass\CoreBundle\Fixtures\Factory\EditionTaskFactory;
use PHPUnit\Framework\TestCase;
use Zenstruck\Foundry\Test\Factories;

final class AbstractApplicationSystemTest extends TestCase
{
    use Factories;

    public function testWithTaskThrowsWhenTaskIsNotAnApplicationSystem(): void
    {
        $task = EditionTaskFactory::new()->ofTypeHostEditingStage()->create();

        $this->expectException(\InvalidArgumentException::class);

        (new FirstComeApplicationSystem())->withTask($task);
    }

    public function testWithTaskThrowsWhenApplicationSystemTypeMismatch(): void
    {
        $lotTask = EditionTaskFactory::new()->ofTypeLotApplicationSystem()->create();

        $this->expectException(\InvalidArgumentException::class);

        (new FirstComeApplicationSystem())->withTask($lotTask);
    }

    public function testWithTaskReturnsNewInstanceAndDoesNotMutate(): void
    {
        $task = EditionTaskFactory::new()->ofTypeFirstComeApplicationSystem()->create();

        $original = new FirstComeApplicationSystem();
        $withTask = $original->withTask($task);

        self::assertNotSame($original, $withTask);
        self::assertNull($original->getTask());
        self::assertSame($task, $withTask->getTask());
    }

    public function testWithTaskWorksForLotSystem(): void
    {
        $task = EditionTaskFactory::new()->ofTypeLotApplicationSystem()->create();

        $system = (new LotApplicationSystem())->withTask($task);

        self::assertSame($task, $system->getTask());
    }

    public function testSuggestTransitionSetsTaskOnAttendance(): void
    {
        $task = EditionTaskFactory::new()->ofTypeFirstComeApplicationSystem()->create();
        $system = (new FirstComeApplicationSystem())->withTask($task);

        $attendance = new \Ferienpass\CoreBundle\Entity\Attendance(
            new \Ferienpass\CoreBundle\Entity\Offer\Base(),
            new \Ferienpass\CoreBundle\Entity\Participant\BaseParticipant()
        );

        self::assertNull($attendance->getTask());

        $system->suggestTransition($attendance);

        self::assertSame($task, $attendance->getTask());
    }
}
