<?php

/**
 * 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.
 */

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\CalendarBundle\Messenger\Doctrine;

use Chill\CalendarBundle\Entity\Calendar;
use Chill\CalendarBundle\Messenger\Message\CalendarMessage;
use Chill\CalendarBundle\Messenger\Message\CalendarRemovedMessage;
use Chill\MainBundle\Entity\User;
use Doctrine\ORM\Event\PostPersistEventArgs;
use Doctrine\ORM\Event\PostRemoveEventArgs;
use Doctrine\ORM\Event\PostUpdateEventArgs;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Security;

class CalendarEntityListener
{
    public function __construct(private readonly MessageBusInterface $messageBus, private readonly Security $security) {}

    private function getAuthenticatedUser(): User
    {
        $user = $this->security->getUser();

        if (!$user instanceof User) {
            throw new \LogicException('Expected an instance of User.');
        }

        return $user;
    }

    public function postPersist(Calendar $calendar, PostPersistEventArgs $args): void
    {
        if (!$calendar->preventEnqueueChanges) {
            $this->messageBus->dispatch(
                new CalendarMessage(
                    $calendar,
                    CalendarMessage::CALENDAR_PERSIST,
                    $this->getAuthenticatedUser()
                )
            );
        }
    }

    public function postRemove(Calendar $calendar, PostRemoveEventArgs $args): void
    {
        if (!$calendar->preventEnqueueChanges) {
            $this->messageBus->dispatch(
                new CalendarRemovedMessage(
                    $calendar,
                    $this->getAuthenticatedUser()
                )
            );
        }
    }

    public function postUpdate(Calendar $calendar, PostUpdateEventArgs $args): void
    {
        if ($calendar->getStatus() === $calendar::STATUS_CANCELED) {
            $this->messageBus->dispatch(
                new CalendarRemovedMessage(
                    $calendar,
                    $this->getAuthenticatedUser()
                )
            );
        } elseif (!$calendar->preventEnqueueChanges) {
            $this->messageBus->dispatch(
                new CalendarMessage(
                    $calendar,
                    CalendarMessage::CALENDAR_UPDATE,
                    $this->getAuthenticatedUser()
                )
            );
        }
    }
}
