<?php

/*
 * This file is part of the Serenity package.
 *
 * (c) CP Creation <web@cpcreation.fr>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Serenity\CoreBundle\Shared\Messenger\Stamp;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;

readonly class DoctrineTransactionWithDryRunMiddleware implements MiddlewareInterface
{
    public function __construct(
        private EntityManagerInterface $em,
    ) {
    }

    public function handle(Envelope $envelope, StackInterface $stack): Envelope
    {
        $conn = $this->em->getConnection();
        $dryRun = null !== $envelope->last(DryRunStamp::class);

        $conn->beginTransaction();

        try {
            $envelope = $stack->next()->handle($envelope, $stack);

            // flush comme doctrine_transaction
            $this->em->flush();

            if ($dryRun) {
                $conn->rollBack();
                $this->em->clear(); // recommandé après rollback

                return $envelope;
            }

            $conn->commit();

            return $envelope;
        } catch (\Throwable $e) {
            if ($conn->isTransactionActive()) {
                $conn->rollBack();
            }
            $this->em->clear();
            throw $e;
        }
    }
}
