<?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\Entity\OfferDate;
use Ferienpass\CoreBundle\Settings\SystemSettingsManager;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\Translation\TranslatableMessage;

#[AsEventListener(priority: 80)]
class AgeInvalidListener
{
    public function __construct(private readonly SystemSettingsManager $systemSettingsManager)
    {
    }

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

        if (!$offer->getMinAge() && !$offer->getMaxAge()) {
            return;
        }

        /** @var OfferDate|false $date */
        $date = $offer->getDates()->first();
        if (false === $date || null === $dateBegin = $date->getBegin()) {
            return;
        }

        $ageTolerance = $this->systemSettingsManager->getAgeTolerance();
        $allowedAges = [$participant->getAge($dateBegin)];
        if (null !== $ageTolerance && '' !== $ageTolerance) {
            $allowedAges[] = $participant->getAge((clone $dateBegin)->modify(\sprintf('-%s', $ageTolerance)));
            $allowedAges[] = $participant->getAge((clone $dateBegin)->modify(\sprintf('+%s', $ageTolerance)));
        }

        if ([] === array_filter($allowedAges, static fn ($age) => null !== $age)) {
            return;
        }

        if (($offer->getMinAge() && max($allowedAges) < $offer->getMinAge()) || ($offer->getMaxAge() && min($allowedAges) > $offer->getMaxAge())) {
            throw new AgeInvalid($offer, $participant, new TranslatableMessage('ineligible.invalidAge', ['name' => $participant->getFirstname(), 'age' => $participant->getAge($dateBegin), 'min' => $offer->getMinAge(), 'max' => $offer->getMaxAge()]));
        }
    }
}
