<?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 Doctrine\DBAL\Connection;
use Ferienpass\CmsBundle\Application\ExclusionReasonEvent;
use Ferienpass\CoreBundle\Entity\User;
use Ferienpass\CoreBundle\Enum\AttendanceStatus;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\Translation\TranslatableMessage;

/**
 * Blocks further anonymous applications while a previous one for the same
 * e-mail address is still waiting for its confirmation link to be clicked —
 * otherwise an unconfirmed applicant could pile up held applications.
 */
#[AsEventListener(priority: 100)]
class UnconfirmedListener
{
    public function __construct(private readonly Connection $connection)
    {
    }

    public function __invoke(ExclusionReasonEvent $event): void
    {
        $offer = $event->getOffer();
        $participant = $event->getParticipant();

        if ($participant->getUser() instanceof User) {
            return;
        }

        $email = (string) $participant->getEmail();
        if ('' === $email) {
            return;
        }

        $pending = $this->connection->fetchOne(
            'SELECT COUNT(*) FROM Attendance a INNER JOIN Participant p ON p.id = a.participant_id WHERE a.status = :status AND p.email = :email AND p.member_id IS NULL',
            ['status' => AttendanceStatus::EMAIL_UNCONFIRMED, 'email' => $email],
        );

        if ($pending > 0) {
            throw new Unconfirmed($offer, $participant, new TranslatableMessage('ineligible.unconfirmedEmail', ['email' => $email]));
        }
    }
}
