<?php

declare(strict_types=1);

namespace App\Tests\Api;

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

/**
 * @internal
 */
class FilterTest extends AbstractApiTestCase
{
    public function testSearchFilterOnName(): void
    {
        $this->createComposant('Pompe hydraulique');
        $this->createComposant('Vanne de contrôle');
        $this->createComposant('Pompe centrifuge');

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

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

    public function testSearchFilterOnReference(): void
    {
        $this->createPiece('Joint A', 'REF-ALPHA');
        $this->createPiece('Joint B', 'REF-BETA');

        $client = $this->createViewerClient();
        $client->request('GET', '/api/pieces?reference=alpha');

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

    public function testOrderFilterAscending(): void
    {
        $this->createProduct('Zebra');
        $this->createProduct('Alpha');

        $client   = $this->createViewerClient();
        $response = $client->request('GET', '/api/products?order[name]=asc');

        $this->assertResponseIsSuccessful();
        $data = $response->toArray();
        $this->assertSame('Alpha', $data['member'][0]['name']);
    }

    public function testOrderFilterDescending(): void
    {
        $this->createProduct('Alpha');
        $this->createProduct('Zebra');

        $client   = $this->createViewerClient();
        $response = $client->request('GET', '/api/products?order[name]=desc');

        $this->assertResponseIsSuccessful();
        $data = $response->toArray();
        $this->assertSame('Zebra', $data['member'][0]['name']);
    }

    public function testExactFilterOnCategory(): void
    {
        $this->createModelType('Pompe', 'POMPE-001', ModelCategory::COMPONENT);
        $this->createModelType('Joint', 'JOINT-001', ModelCategory::PIECE);
        $this->createModelType('Huile', 'HUILE-001', ModelCategory::PRODUCT);

        $client = $this->createViewerClient();
        $client->request('GET', '/api/model_types?category=PIECE');

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

    public function testExistsFilterOnDocuments(): void
    {
        $machine = $this->createMachine('Machine A');
        $site    = $this->createSite('Site B');

        $doc1 = new Document();
        $doc1->setName('doc1');
        $doc1->setFilename('f1.pdf');
        $doc1->setPath('/uploads/f1.pdf');
        $doc1->setMimeType('application/pdf');
        $doc1->setSize(100);
        $doc1->setMachine($machine);

        $doc2 = new Document();
        $doc2->setName('doc2');
        $doc2->setFilename('f2.pdf');
        $doc2->setPath('/uploads/f2.pdf');
        $doc2->setMimeType('application/pdf');
        $doc2->setSize(200);
        $doc2->setSite($site);

        $em = $this->getEntityManager();
        $em->persist($doc1);
        $em->persist($doc2);
        $em->flush();

        $client = $this->createViewerClient();
        $client->request('GET', '/api/documents?exists[machine]=true');

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

    public function testOrSearchByNameOnPieces(): void
    {
        $this->createPiece('Joint torique', 'REF-JT-001');
        $this->createPiece('Roulement', 'REF-RL-002');

        $client = $this->createViewerClient();
        $client->request('GET', '/api/pieces?q=joint');

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

    public function testOrSearchByReferenceOnPieces(): void
    {
        $this->createPiece('Joint torique', 'REF-JT-001');
        $this->createPiece('Roulement', 'REF-RL-002');

        $client = $this->createViewerClient();
        $client->request('GET', '/api/pieces?q=RL-002');

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

    public function testOrSearchMatchesBothNameAndReference(): void
    {
        $this->createComposant('Pompe REF-X', 'REF-POMPE-01');
        $this->createComposant('Vanne', 'REF-VANNE-01');
        $this->createComposant('Moteur', 'POMPE-MOTEUR');

        $client = $this->createViewerClient();
        $client->request('GET', '/api/composants?q=pompe');

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

    public function testOrSearchEmptyQueryReturnsAll(): void
    {
        $this->createProduct('Produit A', 'REF-A');
        $this->createProduct('Produit B', 'REF-B');

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

        $this->assertResponseIsSuccessful();
        $data = $client->getResponse()->toArray();
        $this->assertGreaterThanOrEqual(2, $data['totalItems']);
    }

    public function testOrSearchOnProducts(): void
    {
        $this->createProduct('Huile moteur', 'HM-500');
        $this->createProduct('Graisse', 'GR-100');

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

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