<?php

declare(strict_types=1);

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

use ApiPlatform\State\SerializerContextBuilderInterface;
use App\Module\Commercial\Domain\Entity\Supplier;
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 `supplier:read:accounting` sur les
 * ressources Supplier, uniquement si l'utilisateur courant a la permission
 * `commercial.suppliers.accounting.view` (cf. spec-back M2 § 2.9 / § 4.1 /
 * § 4.2). Jumeau de ClientReadGroupContextBuilder (M1).
 *
 * 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 Supplier : liste ET
 * detail. Sans la permission, les champs comptables (siren, accountNumber,
 * tvaMode, nTva, paymentDelay, paymentType, bank) ET les RIB embarques (groupe
 * supplier: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 -10 : on s'empile APRES ClientReadGroupContextBuilder
 * (priorite par defaut 0) sur le meme service `api_platform.serializer.context_builder`.
 * Les deux decorateurs passent la main pour toute ressource autre que la leur :
 * l'ordre de chainage n'a donc aucun effet fonctionnel, la priorite explicite ne
 * sert qu'a lever l'ambiguite de deux decorateurs sur un meme service.
 */
#[AsDecorator(decorates: 'api_platform.serializer.context_builder', priority: -10)]
final readonly class SupplierReadGroupContextBuilder 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 Supplier, avec la permission.
        if (!$normalization) {
            return $context;
        }

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

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

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

        return $context;
    }
}
