<?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\Handler;

use Chill\CalendarBundle\Entity\CalendarRange;
use Chill\CalendarBundle\Entity\Invite;
use Chill\CalendarBundle\Messenger\Message\CalendarMessage;
use Chill\CalendarBundle\RemoteCalendar\Connector\RemoteCalendarConnectorInterface;
use Chill\CalendarBundle\Repository\CalendarRangeRepository;
use Chill\CalendarBundle\Repository\CalendarRepository;
use Chill\CalendarBundle\Repository\InviteRepository;
use Chill\MainBundle\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

/**
 * Write calendar creation / update to the remote calendar.
 *
 * @AsMessageHandler
 */
class CalendarToRemoteHandler implements MessageHandlerInterface
{
    public function __construct(private readonly CalendarRangeRepository $calendarRangeRepository, private readonly CalendarRepository $calendarRepository, private readonly EntityManagerInterface $entityManager, private readonly InviteRepository $inviteRepository, private readonly RemoteCalendarConnectorInterface $calendarConnector, private readonly UserRepository $userRepository) {}

    public function __invoke(CalendarMessage $calendarMessage)
    {
        $calendar = $this->calendarRepository->find($calendarMessage->getCalendarId());

        if (null === $calendar) {
            return;
        }

        if (null !== $calendarMessage->getPreviousCalendarRangeId()) {
            $previousCalendarRange = $this->calendarRangeRepository
                ->find($calendarMessage->getPreviousCalendarRangeId());
        } else {
            $previousCalendarRange = null;
        }

        if (null !== $calendarMessage->getPreviousMainUserId()) {
            $previousMainUser = $this->userRepository
                ->find($calendarMessage->getPreviousMainUserId());
        } else {
            $previousMainUser = null;
        }

        $newInvites = array_filter(
            array_map(
                fn ($id) => $this->inviteRepository->find($id),
                $calendarMessage->getNewInvitesIds(),
            ),
            static fn (?Invite $invite) => null !== $invite
        );

        $this->calendarConnector->syncCalendar(
            $calendar,
            $calendarMessage->getAction(),
            $previousCalendarRange,
            $previousMainUser,
            $calendarMessage->getOldInvites(),
            $newInvites
        );

        $calendar->preventEnqueueChanges = true;

        if ($calendar->hasCalendarRange()) {
            $calendar->getCalendarRange()->preventEnqueueChanges = true;
        }

        if ($previousCalendarRange instanceof CalendarRange) {
            $previousCalendarRange->preventEnqueueChanges = true;
        }

        $this->entityManager->flush();
    }
}
