<?php

declare(strict_types=1);

/*
 * This file is part of the Ferienpass package.
 *
 * (c) Richard Henkenjohann <richard@ferienpass.online>
 *
 * For more information visit the project website <https://ferienpass.online>
 * or the documentation under <https://docs.ferienpass.online>.
 */

namespace Ferienpass\CoreBundle\Messenger;

use Ferienpass\CoreBundle\Message\GroupedMessageInterface;
use Ferienpass\CoreBundle\Message\LoggableMessageInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;
use Symfony\Component\Messenger\Stamp\HandlerArgumentsStamp;

class MessageLogMiddleware implements MiddlewareInterface
{
    public function __construct(private readonly LoggerInterface $messagesLogger)
    {
    }

    public function handle(Envelope $envelope, StackInterface $stack): Envelope
    {
        if (!$envelope->last(UuidStamp::class) instanceof \Symfony\Component\Messenger\Stamp\StampInterface) {
            $envelope = $envelope->with(new UuidStamp());
        }

        $uuid = $envelope->last(UuidStamp::class)->getUuid();
        $envelope = $envelope->with(new HandlerArgumentsStamp([
            $uuid,
        ]));

        $message = $envelope->getMessage();
        if (!$message instanceof LoggableMessageInterface) {
            return $stack->next()->handle($envelope, $stack);
        }

        $context = [
            'uuid' => $uuid,
            'class' => $message::class,
            'related' => $message->getRelated(),
        ];

        if ($message instanceof GroupedMessageInterface) {
            $context['group'] = $message->groupedBy();
        }

        $this->messagesLogger->info('Handling message {class}', $context);

        return $stack->next()->handle($envelope, $stack);
    }
}
