<?php

declare(strict_types=1);

namespace App\Module\Technique\Infrastructure\ApiPlatform\Serializer;

use ApiPlatform\State\SerializerContextBuilderInterface;
use App\Module\Technique\Domain\Entity\Provider;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
use Symfony\Component\HttpFoundation\Request;

/**
 * Decore le context builder de serialisation d'API Platform pour ajouter
 * DYNAMIQUEMENT le groupe de lecture `provider:read:accounting` sur les
 * ressources Provider, uniquement si l'utilisateur courant a la permission
 * `technique.providers.accounting.view` (cf. spec-back M3 § 2.9 / § 4.1 /
 * § 4.2). Jumeau de SupplierReadGroupContextBuilder (M2).
 *
 * Pourquoi un context builder et pas le Provider : un Provider retourne des
 * donnees mais ne peut pas influencer les groupes de serialisation. Le contexte
 * de normalisation est construit ici, en amont du serializer — c'est le point
 * d'extension idiomatique d'API Platform pour conditionner un groupe selon
 * l'utilisateur. Realise l'intention « gating du groupe accounting » de la spec
 * (le groupe n'est jamais pose par defaut sur l'operation : il est AJOUTE ici si
 * la permission est presente — resultat identique au « retrait » decrit en spec).
 *
 * S'applique aux operations de LECTURE (normalization) sur Provider : liste ET
 * detail. Sans la permission, les champs comptables (siren, accountNumber,
 * tvaMode, nTva, paymentDelay, paymentType, bank) ET les RIB embarques (groupe
 * provider:read:accounting porte par getRibs()) ne sont jamais serialises — la
 * cle est totalement absente du JSON (gating par omission, parade bug #4 M1).
 *
 * Priorite de decoration -20 : on s'empile APRES les decorateurs Commercial
 * (ClientReadGroupContextBuilder priorite 0, SupplierReadGroupContextBuilder
 * priorite -10) sur le meme service `api_platform.serializer.context_builder`.
 * Chaque decorateur passe la main pour toute ressource autre que la sienne :
 * l'ordre de chainage n'a donc aucun effet fonctionnel, la priorite explicite ne
 * sert qu'a lever l'ambiguite de plusieurs decorateurs sur un meme service.
 */
#[AsDecorator(decorates: 'api_platform.serializer.context_builder', priority: -20)]
final readonly class ProviderReadGroupContextBuilder implements SerializerContextBuilderInterface
{
    public function __construct(
        #[AutowireDecorated]
        private SerializerContextBuilderInterface $decorated,
        private Security $security,
    ) {}

    public function createFromRequest(Request $request, bool $normalization, ?array $extractedAttributes = null): array
    {
        $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);

        // Uniquement en lecture, sur la ressource Provider, avec la permission.
        if (!$normalization) {
            return $context;
        }

        if (Provider::class !== ($context['resource_class'] ?? null)) {
            return $context;
        }

        if (!$this->security->isGranted('technique.providers.accounting.view')) {
            return $context;
        }

        $groups = $context['groups'] ?? [];
        if (!in_array('provider:read:accounting', $groups, true)) {
            $groups[] = 'provider:read:accounting';
        }
        $context['groups'] = $groups;

        return $context;
    }
}
