<?php
namespace App\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\Contract;
use App\Message\SendNewContractNotification;
use App\Message\SendUpdateContractOperatorNotification;
use App\Message\SendUpdateContractItineraryNotification;
use App\Message\SendUpdateContractStatusNotification;
use App\Message\SendUpdateContractStatusCompletedNotification;
use App\Message\SendNewReportedIncidentNotification;
use App\Message\SendUpdateContractDemurrageStatusPaidNotification;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request;
// use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Messenger\MessageBusInterface;
// use App\Entity\User;
// use App\Service\NotificationService;
use Doctrine\ORM\EntityManagerInterface;
// use Psr\Log\LoggerInterface;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\UnitOfWork;
final class ContractSubscriber implements EventSubscriberInterface
{
public function __construct(
// TokenStorageInterface $tokenStorage,
private readonly MessageBusInterface $messageBus,
// private readonly NotificationService $notification // quitar
private readonly EntityManagerInterface $entityManager,
// private readonly LoggerInterface $logger, // 👈 añadido
) {}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::VIEW => [
['detectPropertyChange', EventPriorities::PRE_WRITE],
['sendNewContractNotification', EventPriorities::POST_WRITE],
['sendUpdateContractOperatorNotification', EventPriorities::POST_WRITE],
['sendUpdateContractItineraryNotification', EventPriorities::POST_WRITE],
['sendUpdateContractStatusNotification', EventPriorities::POST_WRITE],
['sendUpdateContractStatusCompletedNotification', EventPriorities::POST_WRITE],
['sendNewReportedIncidentNotification', EventPriorities::POST_WRITE],
['sendUpdateContractDemurrageStatusPaidNotification', EventPriorities::POST_WRITE],
],
];
}
public function detectPropertyChange(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
$uow = $this->entityManager->getUnitOfWork();
$originalData = $uow->getOriginalEntityData($contract);
$oldOperator = $originalData['operator']?->getId() ?? null;
$newOperator = $contract->getOperator()?->getId();
if ($oldOperator !== $newOperator) {
$event->getRequest()->attributes->set('operator_changed', true);
}
$oldPortCalls = $originalData['portCalls'] ?? null;
$newPortCalls = $contract->getPortCalls();
if ($oldPortCalls instanceof Collection && $newPortCalls instanceof Collection) {
if ($this->collectionsAreDifferent($oldPortCalls, $newPortCalls, $uow)) {
$event->getRequest()->attributes->set('portCalls_changed', true);
}
}
$oldStatus = $originalData['status'] ?? null;
$newStatus = $contract->getStatus();
if ($oldStatus !== $newStatus) {
$event->getRequest()->attributes->set('status_changed', true);
}
if ($newStatus === 'OPERATIONS_COMPLETED') {
$event->getRequest()->attributes->set('statusCompleted_changed', true);
}
$oldOperationReports = $originalData['operationReports'] ?? null;
$newOperationReports = $contract->getOperationReports();
if ($oldOperationReports instanceof Collection && $newOperationReports instanceof Collection) {
if ($this->collectionsAreDifferent($oldOperationReports, $newOperationReports, $uow)) {
$event->getRequest()->attributes->set('operationReports_changed', true);
}
}
$oldDemurrageStatus = $originalData['demurrageStatus'] ?? null;
$newDemurrageStatus = $contract->getDemurrageStatus();
if ($oldDemurrageStatus !== $newDemurrageStatus) {
$event->getRequest()->attributes->set('demurrageStatus_changed', true);
}
if ($newDemurrageStatus === 'PAID') {
$event->getRequest()->attributes->set('demurrageStatusPaid_changed', true);
}
// $this->logger->info('___DEBUG___', [
// 'oldOperator' => $oldOperator,
// 'newOperator' => $newOperator,
// 'different' => $oldOperator !== $newOperator
// ]);
// $this->logger->info('___DEBUG___', [
// 'oldPortCalls' => $oldPortCalls,
// 'newPortCalls' => $newPortCalls,
// 'different' => $this->collectionsAreDifferent($oldPortCalls, $newPortCalls, $uow)
// ]);
// $this->logger->info('___DEBUG___', [
// 'oldStatus' => $oldStatus,
// 'newStatus' => $newStatus,
// 'different' => $oldStatus !== $newStatus
// ]);
// $this->logger->info('___DEBUG___', [
// 'oldReportedIncidents' => $oldReportedIncidents,
// 'newReportedIncidents' => $newReportedIncidents,
// 'different' => $this->collectionsAreDifferent($oldReportedIncidents, $newReportedIncidents, $uow)
// ]);
// $this->logger->info('___DEBUG___', [
// 'oldDemurrageStatus' => $oldDemurrageStatus,
// 'newDemurrageStatus' => $newDemurrageStatus,
// 'different' => $oldDemurrageStatus !== $newDemurrageStatus
// ]);
}
public function sendNewContractNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_POST !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
$message = new SendNewContractNotification();
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendNewContractNotification($contract->getId());
}
public function sendUpdateContractOperatorNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
// $this->logger->info('___DEBUG___', [
// 'operator_changed' => $event->getRequest()->attributes->get('operator_changed', false)
// ]);
if (!$event->getRequest()->attributes->get('operator_changed', false)) {
return;
}
$message = new SendUpdateContractOperatorNotification();
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendUpdateContractOperatorNotification($contract->getId());
}
public function sendUpdateContractItineraryNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
// $this->logger->info('___DEBUG___', [
// 'portCalls_changed' => $event->getRequest()->attributes->get('portCalls_changed', false)
// ]);
if (!$event->getRequest()->attributes->get('portCalls_changed', false)) {
return;
}
$message = new SendUpdateContractItineraryNotification();
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendUpdateContractItineraryNotification($contract->getId());
}
public function sendUpdateContractStatusNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
// $this->logger->info('___DEBUG___', [
// 'status_changed' => $event->getRequest()->attributes->get('status_changed', false)
// ]);
if (!$event->getRequest()->attributes->get('status_changed', false)) {
return;
}
$message = new SendUpdateContractStatusNotification;
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendUpdateContractStatusNotification($contract->getId());
}
public function sendUpdateContractStatusCompletedNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
// $this->logger->info('___DEBUG___', [
// 'statusCompleted_changed' => $event->getRequest()->attributes->get('statusCompleted_changed', false)
// ]);
if (!$event->getRequest()->attributes->get('statusCompleted_changed', false)) {
return;
}
$message = new SendUpdateContractStatusCompletedNotification;
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendUpdateContractStatusCompletedNotification($contract->getId());
}
public function sendNewReportedIncidentNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
// $this->logger->info('___DEBUG___', [
// 'reportedIncidents_changed' => $event->getRequest()->attributes->get('reportedIncidents_changed', false)
// ]);
if (!$event->getRequest()->attributes->get('operationReports_changed', false)) {
return;
}
$message = new SendNewReportedIncidentNotification();
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendNewReportedIncidentNotification($contract->getId());
}
public function sendUpdateContractDemurrageStatusPaidNotification(ViewEvent $event): void
{
$contract = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
if (!$contract instanceof Contract || Request::METHOD_PUT !== $method) {
return;
}
// $token = $this->tokenStorage->getToken();
// if (!$token) {
// return;
// }
// $user = $token->getUser();
// if (!$user instanceof User) {
// return;
// }
// $this->logger->info('___DEBUG___', [
// 'demurrageStatusPaid_changed' => $event->getRequest()->attributes->get('demurrageStatusPaid_changed', false)
// ]);
if (!$event->getRequest()->attributes->get('demurrageStatusPaid_changed', false)) {
return;
}
$message = new SendUpdateContractDemurrageStatusPaidNotification;
$message->setContractId($contract->getId());
$this->messageBus->dispatch($message);
// $this->notification->sendUpdateContractDemurrageStatusPaidNotification($contract->getId());
}
private function collectionsAreDifferent(Collection $old, Collection $new, UnitOfWork $uow): bool
{
$uow->computeChangeSets();
$oldIds = array_map(fn($entity) => $entity->getId(), $old->toArray());
$newIds = array_map(fn($entity) => $entity->getId(), $new->toArray());
sort($oldIds);
sort($newIds);
if ($oldIds !== $newIds) {
return true;
}
foreach ($new as $entity) {
$changes = $uow->getEntityChangeSet($entity);
if (!empty($changes)) {
return true;
}
}
return false;
}
}