<?php

declare(strict_types=1);

namespace App\Shared\Infrastructure\Messenger;

use App\Shared\Infrastructure\Tenant\TenantDatabaseSwitcher;
use App\Shared\Infrastructure\Tenant\TenantId;
use App\Shared\Infrastructure\Tenant\TenantRegistry;
use Symfony\Component\Messenger\Envelope;
use Symfony\Component\Messenger\Middleware\MiddlewareInterface;
use Symfony\Component\Messenger\Middleware\StackInterface;

final readonly class TenantDatabaseMiddleware implements MiddlewareInterface
{
    public function __construct(
        private TenantRegistry $tenantRegistry,
        private TenantDatabaseSwitcher $databaseSwitcher,
        private TenantMessageTenantIdResolver $tenantIdResolver,
    ) {
    }

    public function handle(Envelope $envelope, StackInterface $stack): Envelope
    {
        $tenantId = $this->tenantIdResolver->resolve($envelope->getMessage());
        if ($tenantId === null) {
            return $stack->next()->handle($envelope, $stack);
        }

        $previousDatabaseUrl = $this->databaseSwitcher->currentDatabaseUrl();
        $tenantConfig = $this->tenantRegistry->getConfig(TenantId::fromString($tenantId));
        $this->databaseSwitcher->useTenantDatabase($tenantConfig->databaseUrl);

        try {
            return $stack->next()->handle($envelope, $stack);
        } finally {
            if ($previousDatabaseUrl !== null) {
                $this->databaseSwitcher->useTenantDatabase($previousDatabaseUrl);
            } else {
                $this->databaseSwitcher->useDefaultDatabase();
            }
        }
    }
}
