<?php

declare(strict_types=1);

namespace App\Tests\Module\Commercial\Api;

/**
 * Tests fonctionnels des RG comptables inter-champs portees par les Assert\Callback
 * de l'entite Supplier (M2, RG-2.07 / RG-2.08), via le PATCH de l'onglet
 * Comptabilite (groupe supplier:write:accounting). On asserte le code HTTP et le
 * propertyPath de la violation (consommable par extractApiViolations cote front,
 * ERP-101). Complete les tests unitaires SupplierValidationTest par la preuve HTTP.
 *
 * @internal
 */
final class SupplierAccountingApiTest extends AbstractSupplierApiTestCase
{
    // === RG-2.07 : Virement impose une banque ===

    public function testVirementWithoutBankReturns422OnBankPath(): void
    {
        $client = $this->createAdminClient();
        $seed   = $this->seedSupplier('Virement No Bank');

        $response = $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
            'headers' => ['Content-Type' => self::MERGE, 'Accept' => self::LD],
            'json'    => ['paymentType' => '/api/payment_types/'.$this->paymentType('VIREMENT')->getId()],
        ]);

        self::assertResponseStatusCodeSame(422);
        self::assertArrayHasKey('bank', $this->violationsByPath($response->toArray(false)));
    }

    public function testVirementWithBankReturns200(): void
    {
        $client = $this->createAdminClient();
        $seed   = $this->seedSupplier('Virement With Bank');

        $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
            'headers' => ['Content-Type' => self::MERGE],
            'json'    => [
                'paymentType' => '/api/payment_types/'.$this->paymentType('VIREMENT')->getId(),
                'bank'        => '/api/banks/'.$this->bank('SG')->getId(),
            ],
        ]);

        self::assertResponseStatusCodeSame(200);
    }

    // === RG-2.08 : LCR impose au moins un RIB ===

    public function testLcrWithoutRibReturns422OnPaymentTypePath(): void
    {
        $client = $this->createAdminClient();
        $seed   = $this->seedSupplier('Lcr No Rib');

        $response = $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
            'headers' => ['Content-Type' => self::MERGE, 'Accept' => self::LD],
            'json'    => ['paymentType' => '/api/payment_types/'.$this->paymentType('LCR')->getId()],
        ]);

        self::assertResponseStatusCodeSame(422);
        // Miroir client : violation portee sur `paymentType` (select « Type de
        // règlement »), `ribs` n'ayant pas de champ de formulaire pour l'ancrer.
        self::assertArrayHasKey('paymentType', $this->violationsByPath($response->toArray(false)));
    }

    public function testLcrWithRibReturns200(): void
    {
        $client = $this->createAdminClient();
        $seed   = $this->seedSupplier('Lcr With Rib');
        $this->addRib($seed);

        $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
            'headers' => ['Content-Type' => self::MERGE],
            'json'    => ['paymentType' => '/api/payment_types/'.$this->paymentType('LCR')->getId()],
        ]);

        self::assertResponseStatusCodeSame(200);
    }

    // === Completude de l'onglet Comptabilite (six scalaires obligatoires) ===

    /**
     * spec-front M2 § Onglet Comptabilite : a la validation COMPLETE de l'onglet
     * (les six champs requis presents dans le payload), chacun vide doit renvoyer
     * une 422 sur son propre propertyPath (mapping inline front, ERP-101). Miroir
     * du comportement client (ClientAccountingCompletenessValidator).
     */
    public function testIncompleteAccountingTabReturns422OnEachField(): void
    {
        $client = $this->createAdminClient();
        $seed   = $this->seedSupplier('Accounting Incomplete');

        $response = $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
            'headers' => ['Content-Type' => self::MERGE, 'Accept' => self::LD],
            'json'    => [
                'siren'         => null,
                'accountNumber' => null,
                'tvaMode'       => null,
                'nTva'          => null,
                'paymentDelay'  => null,
                'paymentType'   => null,
            ],
        ]);

        self::assertResponseStatusCodeSame(422);
        $paths = $this->violationsByPath($response->toArray(false));
        self::assertArrayHasKey('siren', $paths);
        self::assertArrayHasKey('accountNumber', $paths);
        self::assertArrayHasKey('tvaMode', $paths);
        self::assertArrayHasKey('nTva', $paths);
        self::assertArrayHasKey('paymentDelay', $paths);
        self::assertArrayHasKey('paymentType', $paths);
    }

    /**
     * Un PATCH ciblant un sous-ensemble de champs comptables n'est PAS une
     * validation d'onglet : la completude ne se declenche pas (edition ponctuelle
     * preservee, cf. validateAccountingCompleteness).
     */
    public function testPartialAccountingPatchSkipsCompleteness(): void
    {
        $client = $this->createAdminClient();
        $seed   = $this->seedSupplier('Accounting Partial');

        $client->request('PATCH', '/api/suppliers/'.$seed->getId(), [
            'headers' => ['Content-Type' => self::MERGE],
            'json'    => ['nTva' => 'FR12345678901'],
        ]);

        self::assertResponseStatusCodeSame(200);
    }

    // violationsByPath() : helper mutualise dans AbstractSupplierApiTestCase.
}
