<?php

namespace App\Shared\Tenant;

use App\Auth\Entity\User;
use App\Shared\Context\EntityContextResolver;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * فیلتر محیط را در ابتدای هر درخواست روشن می‌کند — و فقط وقتی که واقعاً محیطی
 * حل شود.
 *
 * دو مسیر عمداً بیرون می‌مانند:
 *   • مسیرهای عمومی مارکت‌پلیس (nobat724_front) کاربر پنل ندارند، پس محیطی حل
 *     نمی‌شود و جستجوی چند-کلینیکی دست‌نخورده کار می‌کند.
 *   • ادمین ذاتاً سراسری است؛ فیلتر کردنش پنل مدیریت را کور می‌کند.
 */
final class TenantFilterSubscriber implements EventSubscriberInterface
{
    public function __construct(
        private readonly Security               $security,
        private readonly EntityContextResolver  $contextResolver,
        private readonly EntityManagerInterface $em,
    ) {}

    public static function getSubscribedEvents(): array
    {
        // بعد از فایروال (اولویت ۸) تا توکن در دسترس باشد.
        return [KernelEvents::REQUEST => ['onRequest', 5]];
    }

    public function onRequest(RequestEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }

        $user = $this->security->getUser();
        if (!$user instanceof User || $user->hasRole('ROLE_ADMIN')) {
            return;
        }

        // فقط محیطِ انتخاب‌شده. کاربری که هنوز محیطی برنگزیده در هیچ محیطی «نیست»؛
        // قفل‌کردنش روی حدسِ نقش، دادهٔ کلینیکی‌ای را که قانوناً حقش است پنهان می‌کند
        // و دسترسی را همان checkerهای دامنه تعیین می‌کنند.
        $context = $this->contextResolver->tryResolve($user);
        if ($context === null || !$context->isResolved() || !$context->chosen) {
            return;
        }

        [$type, $id] = $context->toEntityPair();

        $this->em->getFilters()
            ->enable(TenantFilter::NAME)
            ->setParameter(TenantFilter::PARAM_TYPE, $type, 'string')
            ->setParameter(TenantFilter::PARAM_ID, $id, 'integer');
    }
}
