<?php

declare(strict_types=1);

namespace App\Module\Commercial\Application\Validator;

use ApiPlatform\Validator\Exception\ValidationException;
use App\Module\Commercial\Domain\Entity\Client;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;

/**
 * Validator metier (spec-front § Onglet Comptabilite) : a la soumission complete
 * de l'onglet Comptabilite, les six champs scalaires obligatoires doivent etre
 * renseignes (SIREN, Numero de compte, Mode de TVA, N de TVA, Delai de reglement,
 * Type de reglement). La banque reste conditionnelle (RG-1.12) et les RIB aussi
 * (RG-1.13) : ils ne sont pas couverts ici.
 *
 * Parti pris : colonnes nullable en base + validateur contextuel, plutot qu'un
 * Assert\NotBlank sur l'entite (qui casserait le POST de l'onglet principal,
 * lequel n'envoie aucun champ comptable).
 *
 * Invoque par le ClientProcessor uniquement quand le payload porte les six champs
 * (= une validation d'onglet), jamais sur un PATCH ciblant un seul champ comptable.
 *
 * Leve une ValidationException (HTTP 422) listant chaque champ manquant, par
 * coherence avec les violations Symfony rendues par API Platform (mapping inline
 * front via useFormErrors, ERP-101).
 */
final class ClientAccountingCompletenessValidator
{
    public function validate(Client $client): void
    {
        // Map champ -> valeur courante des champs obligatoires de l'onglet.
        $fields = [
            'siren'         => $client->getSiren(),
            'accountNumber' => $client->getAccountNumber(),
            'tvaMode'       => $client->getTvaMode(),
            'nTva'          => $client->getNTva(),
            'paymentDelay'  => $client->getPaymentDelay(),
            'paymentType'   => $client->getPaymentType(),
        ];

        $violations = new ConstraintViolationList();

        foreach ($fields as $property => $value) {
            if ($this->isMissing($value)) {
                $violations->add(new ConstraintViolation(
                    'Ce champ est obligatoire.',
                    null,
                    [],
                    $client,
                    $property,
                    $value,
                ));
            }
        }

        if (count($violations) > 0) {
            throw new ValidationException($violations);
        }
    }

    /**
     * Une valeur est manquante si null ou, pour une chaine, vide apres trim. Les
     * references (TvaMode / PaymentDelay / PaymentType) ne sont manquantes que
     * lorsqu'elles valent null.
     */
    private function isMissing(mixed $value): bool
    {
        if (null === $value) {
            return true;
        }

        return is_string($value) && '' === trim($value);
    }
}
