<?php

declare(strict_types=1);

namespace App\Tests\Api\Entity;

use App\Enum\ModelCategory;
use App\Tests\AbstractApiTestCase;

/**
 * @internal
 */
class ProductTest extends AbstractApiTestCase
{
    public function testGetCollection(): void
    {
        $this->createProduct('Produit A');
        $this->createProduct('Produit B');

        $client = $this->createViewerClient();
        $client->request('GET', '/api/products');

        $this->assertResponseIsSuccessful();
        $this->assertJsonContainsHydraCollection();
        $this->assertJsonContains(['totalItems' => 2]);
    }

    public function testGetItem(): void
    {
        $p = $this->createProduct('Produit A', 'REF-P001');

        $client = $this->createViewerClient();
        $client->request('GET', self::iri('products', $p->getId()));

        $this->assertResponseIsSuccessful();
        $this->assertJsonContains([
            'name'      => 'Produit A',
            'reference' => 'REF-P001',
        ]);
    }

    public function testPost(): void
    {
        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/products', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'          => 'Nouveau produit',
                'reference'     => 'REF-NEW',
                'supplierPrice' => '99.99',
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
        $this->assertJsonContains(['name' => 'Nouveau produit']);
    }

    public function testPostWithType(): void
    {
        $mt = $this->createModelType('Huile', 'HUILE-001', ModelCategory::PRODUCT);

        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/products', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'        => 'Produit typé',
                'typeProduct' => self::iri('model_types', $mt->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
    }

    public function testPut(): void
    {
        $p = $this->createProduct('Produit A');

        $client = $this->createGestionnaireClient();
        $client->request('PUT', self::iri('products', $p->getId()), [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => ['name' => 'Produit A Renommé'],
        ]);

        $this->assertResponseIsSuccessful();
        $this->assertJsonContains(['name' => 'Produit A Renommé']);
    }

    public function testPatch(): void
    {
        $p = $this->createProduct('Produit A');

        $client = $this->createGestionnaireClient();
        $client->request('PATCH', self::iri('products', $p->getId()), [
            'headers' => ['Content-Type' => 'application/merge-patch+json'],
            'json'    => ['supplierPrice' => '150.00'],
        ]);

        $this->assertResponseIsSuccessful();
        $this->assertJsonContains(['supplierPrice' => '150.00']);
    }

    public function testDelete(): void
    {
        $p = $this->createProduct('ToDelete');

        $client = $this->createGestionnaireClient();
        $client->request('DELETE', self::iri('products', $p->getId()));

        $this->assertResponseStatusCodeSame(204);
    }

    public function testUnauthenticatedAccess(): void
    {
        $client = $this->createUnauthenticatedClient();
        $client->request('GET', '/api/products');

        $this->assertResponseStatusCodeSame(401);
    }

    public function testViewerCannotWrite(): void
    {
        $client = $this->createViewerClient();
        $client->request('POST', '/api/products', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => ['name' => 'Blocked'],
        ]);

        $this->assertResponseStatusCodeSame(403);
    }

    public function testSearchFilter(): void
    {
        $this->createProduct('Huile moteur');
        $this->createProduct('Filtre à air');

        $client = $this->createViewerClient();
        $client->request('GET', '/api/products?name=huile');

        $this->assertResponseIsSuccessful();
        $this->assertJsonContains(['totalItems' => 1]);
    }
}
