<?php

declare(strict_types=1);

namespace App\Module\Technique\Infrastructure\ApiPlatform\State\Provider;

use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Module\Technique\Domain\Entity\ProviderOwnedInterface;
use App\Module\Technique\Infrastructure\Security\ProviderSiteScopeChecker;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

/**
 * Provider d'item des sous-ressources d'un prestataire (Contact / Adresse / RIB).
 * Decore le provider Doctrine par defaut et applique le cloisonnement par site du
 * PARENT (§ 2.13 / RG-3.17) sur Get / Patch / Delete.
 *
 * Sans ce garde, un user cloisonne pourrait lire / editer / supprimer une
 * sous-ressource d'un prestataire hors de son site : le detail Provider est bien
 * garde en 404 (ProviderProvider), mais les sous-ressources ne passent pas par lui
 * (provider Doctrine par defaut, et SiteScopedQueryExtension ne filtre que les
 * resources SiteAwareInterface — ce que ces entites ne sont pas). Le RIB est
 * particulierement sensible (IBAN / BIC).
 *
 * Hors perimetre -> retour null -> 404 (anti-enumeration, coherent avec le detail
 * Provider). La decision de scope est deleguee a ProviderSiteScopeChecker (source
 * unique partagee avec le ProviderProvider et les processors).
 *
 * @implements ProviderInterface<ProviderOwnedInterface>
 */
final class ProviderSubResourceItemProvider implements ProviderInterface
{
    public function __construct(
        #[Autowire(service: 'api_platform.doctrine.orm.state.item_provider')]
        private readonly ProviderInterface $itemProvider,
        private readonly ProviderSiteScopeChecker $scopeChecker,
    ) {}

    public function provide(Operation $operation, array $uriVariables = [], array $context = []): ?object
    {
        $entity = $this->itemProvider->provide($operation, $uriVariables, $context);

        if ($entity instanceof ProviderOwnedInterface) {
            $parent = $entity->getProvider();
            if (null === $parent || !$this->scopeChecker->isInScope($parent)) {
                return null;
            }
        }

        return $entity;
    }
}
