<?php

namespace App\Tests\EventSubscriber;

use App\Entity\MessengerLog;
use App\EventSubscriber\MessengerFailureSubscriber;
use Doctrine\ORM\EntityManagerInterface;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Event\WorkerMessageFailedEvent;
use Symfony\Component\Messenger\Stamp\RedeliveryStamp;
use Symfony\Component\Mime\Email;

class MessengerFailureSubscriberTest extends TestCase
{
    private EntityManagerInterface $em;
    private MailerInterface $mailer;
    private MessengerFailureSubscriber $subscriber;

    protected function setUp(): void
    {
        $this->em = $this->createStub(EntityManagerInterface::class);
        $this->mailer = $this->createStub(MailerInterface::class);
        $this->subscriber = new MessengerFailureSubscriber($this->em, $this->mailer, 'admin@test.com');
    }

    public function testGetSubscribedEvents(): void
    {
        $this->assertArrayHasKey(WorkerMessageFailedEvent::class, MessengerFailureSubscriber::getSubscribedEvents());
    }

    public function testOnMessageFailed(): void
    {
        $message = new \stdClass();
        $envelope = new Envelope($message, [new RedeliveryStamp(1)]);
        $throwable = new \Exception('Worker error');
        $event = new WorkerMessageFailedEvent($envelope, 'async', $throwable);

        $this->em->method('persist');
        $this->em->method('flush');

        $this->mailer->method('send');

        $this->subscriber->onMessageFailed($event);
        $this->addToAssertionCount(1);
    }

    public function testOnMessageFailedNonSerializable(): void
    {
        // Anonymous class is not serializable
        $message = new class {};
        $envelope = new Envelope($message);
        $event = new WorkerMessageFailedEvent($envelope, 'async', new \Exception('error'));

        $this->em->method('persist');

        $this->subscriber->onMessageFailed($event);
        $this->addToAssertionCount(1);
    }

    public function testOnMessageFailedMailerThrows(): void
    {
        $message = new \stdClass();
        $envelope = new Envelope($message);
        $event = new WorkerMessageFailedEvent($envelope, 'async', new \Exception('error'));

        $this->em->method('persist');
        $this->mailer->method('send')->willThrowException(new \RuntimeException('mailer error'));

        // Should not crash, just log error internally (via error_log)
        $this->subscriber->onMessageFailed($event);
        $this->addToAssertionCount(1);
    }
}
