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

use Chill\TicketBundle\Action\Ticket\ChangeEmergencyStateCommand;
use Chill\TicketBundle\Action\Ticket\ReplaceMotiveCommand;
use Chill\TicketBundle\Entity\MotiveHistory;
use Chill\TicketBundle\Entity\Ticket;
use Chill\TicketBundle\Event\MotiveUpdateEvent;
use Chill\TicketBundle\Event\TicketUpdateEvent;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Clock\ClockInterface;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

class ReplaceMotiveCommandHandler
{
    public function __construct(
        private readonly ClockInterface $clock,
        private readonly EntityManagerInterface $entityManager,
        private readonly ChangeEmergencyStateCommandHandler $changeEmergencyStateCommandHandler,
        private readonly EventDispatcherInterface $eventDispatcher,
    ) {}

    public function handle(Ticket $ticket, ReplaceMotiveCommand $command): void
    {
        if (null === $command->motive) {
            throw new \InvalidArgumentException('The new motive cannot be null');
        }

        $event = new MotiveUpdateEvent($ticket);

        // will add if there are no existing motive
        $readyToAdd = 0 === count($ticket->getMotiveHistories());

        foreach ($ticket->getMotiveHistories() as $history) {
            if (null !== $history->getEndDate()) {
                continue;
            }

            if ($history->getMotive() === $command->motive) {
                // we apply the same motive, we do nothing
                continue;
            }

            // collect previous active motives before closing
            $event->previousMotive = $history->getMotive();
            $history->setEndDate($this->clock->now());
            $readyToAdd = true;
        }

        if ($readyToAdd) {
            $history = new MotiveHistory($command->motive, $ticket, $this->clock->now());
            $this->entityManager->persist($history);
            $event->newMotive = $command->motive;

            // Check if the motive has makeTicketEmergency set and update the ticket's emergency status if needed
            if ($command->motive->isMakeTicketEmergency()) {
                $changeEmergencyCommand = new ChangeEmergencyStateCommand($command->motive->getMakeTicketEmergency());
                ($this->changeEmergencyStateCommandHandler)($ticket, $changeEmergencyCommand);
            }
        }

        if ($event->hasChanges()) {
            $this->eventDispatcher->dispatch($event, TicketUpdateEvent::class);
        }
    }
}
