<?php

declare(strict_types=1);

namespace App\Module\Commercial\Application\Validator;

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

/**
 * Validator metier (spec-front M2 § 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-2.07) et
 * les RIB aussi (RG-2.08) : ils ne sont pas couverts ici (Assert\Callback sur
 * l'entite Supplier — validatePaymentTypeConsistency).
 *
 * Parti pris (miroir ClientAccountingCompletenessValidator M1) : 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 SupplierProcessor uniquement quand le payload porte les six
 * champs (= une validation d'onglet), jamais sur un PATCH ciblant un seul champ.
 *
 * 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 SupplierAccountingCompletenessValidator
{
    public function validate(Supplier $supplier): void
    {
        // Map champ -> valeur courante des champs obligatoires de l'onglet.
        $fields = [
            'siren'         => $supplier->getSiren(),
            'accountNumber' => $supplier->getAccountNumber(),
            'tvaMode'       => $supplier->getTvaMode(),
            'nTva'          => $supplier->getNTva(),
            'paymentDelay'  => $supplier->getPaymentDelay(),
            'paymentType'   => $supplier->getPaymentType(),
        ];

        $violations = new ConstraintViolationList();

        foreach ($fields as $property => $value) {
            if ($this->isMissing($value)) {
                $violations->add(new ConstraintViolation(
                    'Ce champ est obligatoire.',
                    null,
                    [],
                    $supplier,
                    $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);
    }
}
