<?php

declare(strict_types=1);

namespace Ferienpass\CoreBundle\Tests\Facade;

use Doctrine\ORM\EntityManagerInterface;
use Ferienpass\CoreBundle\ApplicationSystem\ApplicationSystems;
use Ferienpass\CoreBundle\Entity\Attendance;
use Ferienpass\CoreBundle\Entity\Offer\Base;
use Ferienpass\CoreBundle\Entity\Participant\BaseParticipant;
use Ferienpass\CoreBundle\Enum\AttendanceStatus;
use Ferienpass\CoreBundle\Facade\AttendanceFacade;
use Ferienpass\CoreBundle\Repository\AttendanceRepository;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Workflow\WorkflowInterface;

final class AttendanceFacadeTest extends TestCase
{
    private function makeFacade(
        ?ApplicationSystems $appSystems = null,
        ?AttendanceRepository $attendances = null,
    ): AttendanceFacade {
        return new AttendanceFacade(
            $this->createMock(MessageBusInterface::class),
            $this->createMock(EntityManagerInterface::class),
            $appSystems ?? $this->createMock(ApplicationSystems::class),
            $attendances ?? $this->createMock(AttendanceRepository::class),
            $this->createMock(WorkflowInterface::class),
        );
    }

    public function testPreviewReturnsAttendanceInstance(): void
    {
        $offer = new Base();
        $participant = new BaseParticipant();

        $appSystems = $this->createMock(ApplicationSystems::class);
        $appSystems->method('findApplicationSystem')->willReturn(null);

        $facade = $this->makeFacade($appSystems);
        $attendance = $facade->preview($offer, $participant);

        self::assertInstanceOf(Attendance::class, $attendance);
        self::assertSame($offer, $attendance->getOffer());
        self::assertSame($participant, $attendance->getParticipant());
    }

    public function testCreateThrowsWhenNotifyTrueButCommitFalse(): void
    {
        $this->expectException(\RuntimeException::class);

        $facade = $this->makeFacade();
        $facade->create(new Base(), new BaseParticipant(), notify: true, commit: false);
    }

    public function testIncreasePriorityDoesNothingWhenNotWaiting(): void
    {
        $offer = new Base();
        $participant = new BaseParticipant();
        $attendance = new Attendance($offer, $participant);
        $attendance->setStatus(AttendanceStatus::CONFIRMED);

        $em = $this->createMock(EntityManagerInterface::class);
        $em->expects(self::never())->method('flush');

        $facade = new AttendanceFacade(
            $this->createMock(MessageBusInterface::class),
            $em,
            $this->createMock(ApplicationSystems::class),
            $this->createMock(AttendanceRepository::class),
            $this->createMock(WorkflowInterface::class),
        );

        $facade->increasePriority($attendance);
    }
}
