<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\PersonBundle\AccompanyingPeriod\Events;

use Chill\MainBundle\Entity\Notification;
use Chill\MainBundle\Entity\User;
use Chill\MainBundle\Notification\NotificationPersisterInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Notification\FlagProviders\DesignatedReferrerNotificationFlagProvider;
use Doctrine\Persistence\Event\LifecycleEventArgs;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Workflow\Event\EnteredEvent;
use Symfony\Contracts\Translation\TranslatorInterface;

class UserRefEventSubscriber implements EventSubscriberInterface
{
    public function __construct(private readonly Security $security, private readonly TranslatorInterface $translator, private readonly \Twig\Environment $engine, private readonly NotificationPersisterInterface $notificationPersister) {}

    public static function getSubscribedEvents(): array
    {
        return [
            'workflow.accompanying_period_lifecycle.entered' => [
                'onStateEntered',
            ],
        ];
    }

    public function onStateEntered(EnteredEvent $enteredEvent): void
    {
        if (
            $enteredEvent->getMarking()->has(AccompanyingPeriod::STEP_CONFIRMED)
            and 'confirm' === $enteredEvent->getTransition()->getName()
        ) {
            $this->onPeriodConfirmed($enteredEvent->getSubject());
        }
    }

    public function postUpdate(AccompanyingPeriod $period, LifecycleEventArgs $args): void
    {
        if ($period->isChangedUser()
            && $period->getUser() !== $this->security->getUser()
            && null !== $period->getUser()
            && AccompanyingPeriod::STEP_DRAFT !== $period->getStep()
            && !$period->isPreventUserIsChangedNotification()
        ) {
            $this->generateNotificationToUser($period);
        }
    }

    private function generateNotificationToUser(AccompanyingPeriod $period)
    {
        $notification = new Notification();

        $urgentStatement =
            $period->isEmergency() ? strtoupper($this->translator->trans('accompanying_period.emergency')).' ' : '';

        $notification
            ->setRelatedEntityId($period->getId())
            ->setRelatedEntityClass(AccompanyingPeriod::class)
            ->setTitle($urgentStatement.$this->translator->trans('period_notification.period_designated_subject'))
            ->setMessage($this->engine->render(
                '@ChillPerson/Notification/accompanying_course_designation.md.twig',
                [
                    'accompanyingCourse' => $period,
                ]
            ))
            ->addAddressee($period->getUser())
            ->setType(DesignatedReferrerNotificationFlagProvider::FLAG);

        $this->notificationPersister->persist($notification);
    }

    private function onPeriodConfirmed(AccompanyingPeriod $period)
    {
        if ($period->getUser() instanceof User
            && $period->getUser() !== $this->security->getUser()) {
            $this->generateNotificationToUser($period);
        }
    }
}
