<?php

declare(strict_types=1);

namespace Ferienpass\CmsBundle\Tests\Application;

use Ferienpass\CmsBundle\Application\AbstractParticipantExclusionReason;
use Ferienpass\CmsBundle\Application\ExclusionReasons\AgeInvalid;
use Ferienpass\CmsBundle\Application\ExclusionReasons\DayLimitReached;
use Ferienpass\CmsBundle\Application\ExclusionReasons\LimitReached;
use Ferienpass\CmsBundle\Application\ExclusionReasons\NoAccessCode;
use Ferienpass\CmsBundle\Application\ExclusionReasons\OverlappingDates;
use Ferienpass\CmsBundle\Application\ExclusionReasons\Unconfirmed;
use Ferienpass\CoreBundle\Entity\Offer\OfferInterface;
use Ferienpass\CoreBundle\Entity\Participant\ParticipantInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\TranslatableMessage;

final class AbstractParticipantExclusionReasonTest extends TestCase
{
    private function makeReason(string $class): AbstractParticipantExclusionReason
    {
        $offer = $this->createMock(OfferInterface::class);
        $participant = $this->createMock(ParticipantInterface::class);
        $message = new TranslatableMessage('some.key');

        return new $class($offer, $participant, $message);
    }

    public function testGetOffer(): void
    {
        $offer = $this->createMock(OfferInterface::class);
        $participant = $this->createMock(ParticipantInterface::class);
        $message = new TranslatableMessage('key');
        $reason = new AgeInvalid($offer, $participant, $message);

        self::assertSame($offer, $reason->getOffer());
    }

    public function testGetParticipant(): void
    {
        $offer = $this->createMock(OfferInterface::class);
        $participant = $this->createMock(ParticipantInterface::class);
        $message = new TranslatableMessage('key');
        $reason = new AgeInvalid($offer, $participant, $message);

        self::assertSame($participant, $reason->getParticipant());
    }

    public function testGetUserMessage(): void
    {
        $offer = $this->createMock(OfferInterface::class);
        $participant = $this->createMock(ParticipantInterface::class);
        $message = new TranslatableMessage('key');
        $reason = new AgeInvalid($offer, $participant, $message);

        self::assertSame($message, $reason->getUserMessage());
    }

    public function testIsException(): void
    {
        $reason = $this->makeReason(AgeInvalid::class);

        self::assertInstanceOf(\Exception::class, $reason);
    }

    public function testGetReasonForAgeInvalid(): void
    {
        $reason = $this->makeReason(AgeInvalid::class);

        self::assertSame('age_invalid', $reason->getReason());
    }

    public function testGetReasonForLimitReached(): void
    {
        $reason = $this->makeReason(LimitReached::class);

        self::assertSame('limit_reached', $reason->getReason());
    }

    public function testGetReasonForDayLimitReached(): void
    {
        $reason = $this->makeReason(DayLimitReached::class);

        self::assertSame('day_limit_reached', $reason->getReason());
    }

    public function testGetReasonForNoAccessCode(): void
    {
        $reason = $this->makeReason(NoAccessCode::class);

        self::assertSame('no_access_code', $reason->getReason());
    }

    public function testGetReasonForOverlappingDates(): void
    {
        $reason = $this->makeReason(OverlappingDates::class);

        self::assertSame('overlapping_dates', $reason->getReason());
    }

    public function testGetReasonForUnconfirmed(): void
    {
        $reason = $this->makeReason(Unconfirmed::class);

        self::assertSame('unconfirmed', $reason->getReason());
    }
}
