<?php

declare(strict_types=1);

namespace App\Shared\Infrastructure\Messenger;

use Psr\Log\LoggerInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
use Symfony\Component\Mime\Email;
use Throwable;
use Twig\Environment;

/**
 * Sends an admin alert email when a message exhausts all retries
 * and lands in the dead-letter queue.
 *
 * The alert contains event type, attempt count, timestamps, and last error
 * but never exposes PII (no user emails, no tokens).
 */
final readonly class DeadLetterAlertHandler
{
    private const int MAX_ERROR_LENGTH = 500;

    public function __construct(
        private MailerInterface $mailer,
        private Environment $twig,
        private LoggerInterface $logger,
        private string $adminEmail,
        private string $fromEmail = 'noreply@classeo.fr',
    ) {
    }

    public function __invoke(WorkerMessageFailedEvent $event): void
    {
        if ($event->willRetry()) {
            return;
        }

        $envelope = $event->getEnvelope();
        $message = $envelope->getMessage();
        $throwable = $event->getThrowable();

        $retryCount = RedeliveryStamp::getRetryCountFromEnvelope($envelope);
        $errorMessage = mb_substr($throwable->getMessage(), 0, self::MAX_ERROR_LENGTH);

        $html = $this->twig->render('emails/dead_letter_alert.html.twig', [
            'eventType' => $message::class,
            'retryCount' => $retryCount,
            'lastError' => $errorMessage,
            'transportName' => $event->getReceiverName(),
        ]);

        $email = (new Email())
            ->from($this->fromEmail)
            ->to($this->adminEmail)
            ->subject('[Classeo] Message en dead-letter : ' . ClassNameHelper::short($message::class))
            ->html($html)
            ->priority(Email::PRIORITY_HIGH);

        try {
            $this->mailer->send($email);
        } catch (Throwable $e) {
            $this->logger->error('Failed to send dead-letter alert email.', [
                'error' => $e->getMessage(),
                'messageType' => $message::class,
            ]);
        }
    }
}
