<?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\CmsBundle\Application\ExclusionReasons;

use Ferienpass\CmsBundle\Application\ExclusionReasonEvent;
use Ferienpass\CoreBundle\ApplicationSystem\FirstComeApplicationSystem;
use Ferienpass\CoreBundle\Entity\Attendance;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\Translation\TranslatableMessage;

#[AsEventListener]
class LimitReachedListener
{
    public function __invoke(ExclusionReasonEvent $event): void
    {
        $offer = $event->getOffer();
        $participant = $event->getParticipant();
        $applicationSystem = $event->getApplicationSystem();

        // The per-phase total (maxApplications) is a lot-only setting — the
        // firstcome task editor never exposes it, so a lingering value (e.g. the
        // default carried over from when the phase was a lot phase) must not be
        // enforced here. Firstcome phases are capped per-day instead, via
        // DayLimitReachedListener (maxApplicationsDay).
        if ($applicationSystem instanceof FirstComeApplicationSystem) {
            return;
        }

        $task = $applicationSystem->getTask();
        if (!$task?->getMaxApplications() || $task->isSkipMaxApplications()) {
            return;
        }

        $attendances = $participant
            ->getAttendancesNotHidden(includedCancelled: false)
            ->filter(static fn (Attendance $a) => $a->getTask()?->getId() === $task->getId())
        ;

        if (\count($attendances) >= $task->getMaxApplications()) {
            throw new LimitReached($offer, $participant, new TranslatableMessage('ineligible.limitReached', ['name' => $participant->getFirstname(), 'max' => $task->getMaxApplications()]));
        }
    }
}
