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

use Ferienpass\CoreBundle\Entity\AccessCode;
use Ferienpass\CoreBundle\Entity\AccessCodeStrategy;
use Ferienpass\CoreBundle\Entity\Participant\ParticipantInterface;
use PHPUnit\Framework\TestCase;

final class AccessCodeStrategyTest extends TestCase
{
    public function testGetIdIsNullByDefault(): void
    {
        $strategy = new AccessCodeStrategy();

        self::assertNull($strategy->getId());
    }

    public function testGetNameReturnsEmptyStringByDefault(): void
    {
        $strategy = new AccessCodeStrategy();

        self::assertSame('', $strategy->getName());
    }

    public function testSetNameUpdatesName(): void
    {
        $strategy = new AccessCodeStrategy();
        $strategy->setName('My Strategy');

        self::assertSame('My Strategy', $strategy->getName());
    }

    public function testGetMaxReturnsOneByDefault(): void
    {
        $strategy = new AccessCodeStrategy();

        self::assertSame(1, $strategy->getMax());
    }

    public function testSetMaxUpdatesMax(): void
    {
        $strategy = new AccessCodeStrategy();
        $strategy->setMax(5);

        self::assertSame(5, $strategy->getMax());
    }

    public function testGetCodesInitiallyEmpty(): void
    {
        $strategy = new AccessCodeStrategy();

        self::assertCount(0, $strategy->getCodes());
    }

    public function testGetCreatedAtIsSetOnConstruct(): void
    {
        $strategy = new AccessCodeStrategy();

        self::assertInstanceOf(\DateTimeInterface::class, $strategy->getCreatedAt());
    }

    public function testAddCodeAddsCode(): void
    {
        $strategy = new AccessCodeStrategy();
        $code = $this->createStub(AccessCode::class);
        $strategy->addCode($code);

        self::assertCount(1, $strategy->getCodes());
    }

    public function testRemoveCodeRemovesCode(): void
    {
        $strategy = new AccessCodeStrategy();
        $code = $this->createStub(AccessCode::class);
        $strategy->addCode($code);
        $strategy->removeCode($code);

        self::assertCount(0, $strategy->getCodes());
    }

    public function testFindCodeReturnsNullWhenNotFound(): void
    {
        $strategy = new AccessCodeStrategy();

        self::assertNull($strategy->findCode('ABC123'));
    }

    public function testFindCodeReturnsMatchingCode(): void
    {
        $strategy = new AccessCodeStrategy();

        $code = $this->createMock(AccessCode::class);
        $code->method('getCode')->willReturn('ABC123');
        $strategy->addCode($code);

        self::assertSame($code, $strategy->findCode('ABC123'));
    }

    public function testIsEnabledParticipantReturnsFalseWhenNoCodeHasParticipant(): void
    {
        $strategy = new AccessCodeStrategy();
        $participant = $this->createStub(ParticipantInterface::class);

        self::assertFalse($strategy->isEnabledParticipant($participant));
    }
}
