<?php

declare(strict_types=1);

namespace App\Tests\Module\Catalog\Api;

/**
 * Tests ERP-78 : le `code` technique stable de Category.
 *
 * Cas couverts :
 *  - POST : le code est auto-genere (slug MAJUSCULE du nom) et expose en lecture ;
 *  - le code est en lecture seule : un `code` envoye dans le payload est ignore
 *    (genere depuis le nom) ;
 *  - deux noms produisant le meme slug recoivent des codes distincts (suffixe).
 *
 * @internal
 */
final class CategoryCodeTest extends AbstractCatalogApiTestCase
{
    public function testPostGeneratesAndExposesCode(): void
    {
        $type   = $this->createCategoryType();
        $client = $this->createAdminClient();

        $response = $client->request('POST', '/api/categories', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'         => self::TEST_CATEGORY_PREFIX.'Agro-alimentaire',
                'categoryTypes' => ['/api/category_types/'.$type->getId()],
            ],
        ]);
        self::assertResponseStatusCodeSame(201);

        $payload = $response->toArray();
        // Slug MAJUSCULE du nom, separateurs non alphanumeriques -> `_`.
        self::assertSame(
            strtoupper(self::TEST_CATEGORY_PREFIX).'AGRO_ALIMENTAIRE',
            $payload['code'],
        );
    }

    public function testCodeIsReadOnlyAndIgnoredFromPayload(): void
    {
        $type   = $this->createCategoryType();
        $client = $this->createAdminClient();

        $response = $client->request('POST', '/api/categories', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'         => self::TEST_CATEGORY_PREFIX.'readonly',
                'categoryTypes' => ['/api/category_types/'.$type->getId()],
                // Le client tente d'imposer un code : doit etre ignore.
                'code'         => 'CLIENT_FORGED',
            ],
        ]);
        self::assertResponseStatusCodeSame(201);

        $payload = $response->toArray();
        self::assertNotSame('CLIENT_FORGED', $payload['code']);
        self::assertSame(strtoupper(self::TEST_CATEGORY_PREFIX).'READONLY', $payload['code']);
    }

    public function testCollidingSlugsGetDistinctCodes(): void
    {
        $type   = $this->createCategoryType();
        $client = $this->createAdminClient();

        // Deux noms differents (donc autorises par uq_category_name_active)
        // mais qui produisent le meme slug -> codes distincts (suffixe `_2`).
        $first = $client->request('POST', '/api/categories', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'         => self::TEST_CATEGORY_PREFIX.'Agro Plus',
                'categoryTypes' => ['/api/category_types/'.$type->getId()],
            ],
        ])->toArray();

        $second = $client->request('POST', '/api/categories', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'         => self::TEST_CATEGORY_PREFIX.'Agro-Plus',
                'categoryTypes' => ['/api/category_types/'.$type->getId()],
            ],
        ])->toArray();

        self::assertResponseStatusCodeSame(201);
        self::assertNotSame($first['code'], $second['code']);
        self::assertStringEndsWith('_2', (string) $second['code']);
    }
}
