<?php

declare(strict_types=1);

namespace App\Tests\Module\Commercial\Unit;

use ApiPlatform\Validator\Exception\ValidationException;
use App\Module\Commercial\Application\Validator\SupplierInformationCompletenessValidator;
use App\Module\Commercial\Domain\Entity\Supplier;
use DateTimeImmutable;
use PHPUnit\Framework\TestCase;

/**
 * Tests unitaires du SupplierInformationCompletenessValidator (RG-2.03) : pour le
 * role Commerciale, TOUS les champs de l'onglet Information sont obligatoires.
 * Chaque champ manquant produit une violation portant son propertyPath (ERP-101).
 *
 * @internal
 */
final class SupplierInformationCompletenessValidatorTest extends TestCase
{
    public function testCompleteInformationPasses(): void
    {
        $supplier = $this->completeSupplier();

        $this->validator()->validate($supplier);

        // Aucune exception levee : la completude est satisfaite.
        $this->addToAssertionCount(1);
    }

    public function testEmptyInformationListsEveryMissingField(): void
    {
        $supplier = new Supplier();
        $supplier->setCompanyName('Recycla SAS'); // onglet principal, hors Information

        try {
            $this->validator()->validate($supplier);
            self::fail('Une ValidationException etait attendue (onglet Information vide).');
        } catch (ValidationException $e) {
            $paths = [];
            foreach ($e->getConstraintViolationList() as $violation) {
                $paths[] = $violation->getPropertyPath();
            }

            // Les 8 champs Information (dont volumeForecast, NEW vs Client) sont
            // tous signales d'un coup, chacun sous son propre propertyPath.
            sort($paths);
            self::assertSame([
                'competitors',
                'description',
                'directorName',
                'employeesCount',
                'foundedAt',
                'profitAmount',
                'revenueAmount',
                'volumeForecast',
            ], $paths);
        }
    }

    public function testPartialInformationReportsOnlyMissingFields(): void
    {
        $supplier = $this->completeSupplier();
        $supplier->setDirectorName(null);
        $supplier->setVolumeForecast(null);

        try {
            $this->validator()->validate($supplier);
            self::fail('Une ValidationException etait attendue (2 champs manquants).');
        } catch (ValidationException $e) {
            $paths = [];
            foreach ($e->getConstraintViolationList() as $violation) {
                $paths[] = $violation->getPropertyPath();
            }

            sort($paths);
            self::assertSame(['directorName', 'volumeForecast'], $paths);
        }
    }

    public function testZeroNumericValuesAreNotMissing(): void
    {
        // employeesCount = 0, profitAmount = "0.00", volumeForecast = 0 sont des
        // valeurs valides (un zero n'est pas une absence) -> pas de violation.
        $supplier = $this->completeSupplier();
        $supplier->setEmployeesCount(0);
        $supplier->setProfitAmount('0.00');
        $supplier->setVolumeForecast(0);

        $this->validator()->validate($supplier);

        $this->addToAssertionCount(1);
    }

    public function testBlankStringIsMissing(): void
    {
        // Une chaine vide apres trim compte comme manquante.
        $supplier = $this->completeSupplier();
        $supplier->setDescription('   ');

        $this->expectException(ValidationException::class);
        $this->validator()->validate($supplier);
    }

    /**
     * Fournisseur dont l'onglet Information est entierement renseigne.
     */
    private function completeSupplier(): Supplier
    {
        $supplier = new Supplier();
        $supplier->setCompanyName('Recycla SAS');
        $supplier->setDescription('Specialiste du recyclage');
        $supplier->setCompetitors('Concurrent A, Concurrent B');
        $supplier->setFoundedAt(new DateTimeImmutable('2010-01-01'));
        $supplier->setEmployeesCount(42);
        $supplier->setRevenueAmount('1000000.00');
        $supplier->setDirectorName('Marie Durand');
        $supplier->setProfitAmount('150000.00');
        $supplier->setVolumeForecast(5000);

        return $supplier;
    }

    private function validator(): SupplierInformationCompletenessValidator
    {
        return new SupplierInformationCompletenessValidator();
    }
}
