<?php

declare(strict_types=1);

namespace App\Tests\Module\Technique\Api;

/**
 * Tests fonctionnels du formulaire principal prestataire (POST + PATCH) — ERP-134.
 * Couvre : creation (RG-3.03 sites obligatoires, RG-3.09 type categorie),
 * normalisation companyName (RG-3.11), 409 doublon (RG-3.10).
 *
 * @internal
 */
final class ProviderApiTest extends AbstractProviderApiTestCase
{
    public function testPostMainCreatesProvider(): void
    {
        $client = $this->createAdminClient();

        $response = $client->request('POST', '/api/providers', [
            'headers' => ['Content-Type' => self::LD],
            'json'    => $this->validMainPayload('Maintenance Pro', [self::SITE_86]),
        ]);

        self::assertSame(201, $response->getStatusCode());
        $body = $response->toArray();
        // RG-3.11 : companyName normalise en MAJUSCULES.
        self::assertSame('MAINTENANCE PRO', $body['companyName']);
        self::assertArrayHasKey('id', $body);
        // sites embarque (relation directe, site:read) avec name/postalCode.
        self::assertCount(1, $body['sites']);
        self::assertSame('86100', $body['sites'][0]['postalCode']);
    }

    public function testPostWithoutSiteIsRejected(): void
    {
        $client = $this->createAdminClient();

        $payload          = $this->validMainPayload('Sans Site', [self::SITE_86]);
        $payload['sites'] = [];

        $response = $client->request('POST', '/api/providers', [
            'headers' => ['Content-Type' => self::LD],
            'json'    => $payload,
        ]);

        // RG-3.03 : au moins un site obligatoire.
        self::assertSame(422, $response->getStatusCode());
        self::assertArrayHasKey('sites', $this->violationsByPath($response->toArray(false)));
    }

    public function testPostWithoutCategoryIsRejected(): void
    {
        $client = $this->createAdminClient();

        $payload               = $this->validMainPayload('Sans Categorie', [self::SITE_86]);
        $payload['categories'] = [];

        $response = $client->request('POST', '/api/providers', [
            'headers' => ['Content-Type' => self::LD],
            'json'    => $payload,
        ]);

        // RG-3.09 : au moins une categorie obligatoire.
        self::assertSame(422, $response->getStatusCode());
        self::assertArrayHasKey('categories', $this->violationsByPath($response->toArray(false)));
    }

    public function testPostWithForeignCategoryTypeIsRejected(): void
    {
        $client  = $this->createAdminClient();
        $foreign = $this->foreignCategory();

        $payload               = $this->validMainPayload('Mauvais Type', [self::SITE_86]);
        $payload['categories'] = ['/api/categories/'.$foreign->getId()];

        $response = $client->request('POST', '/api/providers', [
            'headers' => ['Content-Type' => self::LD],
            'json'    => $payload,
        ]);

        // RG-3.09 : categorie hors type PRESTATAIRE -> 422 sur `categories`.
        self::assertSame(422, $response->getStatusCode());
        self::assertArrayHasKey('categories', $this->violationsByPath($response->toArray(false)));
    }

    public function testDuplicateCompanyNameReturns409(): void
    {
        $this->seedProvider('Doublon Sarl', [self::SITE_86]);
        $client = $this->createAdminClient();

        $response = $client->request('POST', '/api/providers', [
            'headers' => ['Content-Type' => self::LD],
            // Casse differente : l'unicite est insensible a la casse (LOWER).
            'json' => $this->validMainPayload('doublon sarl', [self::SITE_86]),
        ]);

        // RG-3.10 : doublon de nom (case-insensitive) -> 409.
        self::assertSame(409, $response->getStatusCode());
    }

    public function testSameNameAfterArchiveIsAllowed(): void
    {
        // Index partiel : l'unicite ignore les archives -> reutilisation du nom OK.
        $this->seedProvider('Recyclage Express', [self::SITE_86], isArchived: true);
        $client = $this->createAdminClient();

        $response = $client->request('POST', '/api/providers', [
            'headers' => ['Content-Type' => self::LD],
            'json'    => $this->validMainPayload('Recyclage Express', [self::SITE_86]),
        ]);

        self::assertSame(201, $response->getStatusCode());
    }
}
