<?php

namespace App\Waitlist\MessageHandler;

use App\Appointment\Entity\Appointment;
use App\Shared\Event\DomainEvents;
use App\Shared\Event\Message\DomainEventMessage;
use App\Waitlist\Service\WaitlistConverter;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

/**
 * وقتی بیمار بالاخره رزرو کرد، ردیف انتظارش `converted` می‌شود.
 *
 * از رویداد می‌آید نه از خودِ `BookingService`: تبدیل، اثر جانبیِ رزرو است نه بخشی از
 * آن، و اگر داخل تراکنش رزرو می‌نشست یک خطای لیست انتظار می‌توانست نوبت واقعی بیمار
 * را برگرداند.
 *
 * **idempotent** است: `WaitlistConverter` ردیفِ از قبل تبدیل‌شده را رد می‌کند، پس تحویل
 * دوبارهٔ پیام چیزی را خراب نمی‌کند.
 */
#[AsMessageHandler]
final class WaitlistConversionHandler
{
    public function __construct(
        private readonly WaitlistConverter      $converter,
        private readonly EntityManagerInterface $em,
    ) {}

    public function __invoke(DomainEventMessage $message): void
    {
        if ($message->name !== DomainEvents::APPOINTMENT_BOOKED) {
            return;
        }

        $uuid = $message->payload['appointment_uuid'] ?? null;

        if (!is_string($uuid)) {
            return;
        }

        $appointment = $this->em->getRepository(Appointment::class)->findOneBy(['uuid' => $uuid]);

        // نوبتِ لغوشده بین انتشار و مصرف: چیزی برای تبدیل نمانده.
        if ($appointment !== null) {
            $this->converter->convertFor($appointment);
        }
    }
}
