<?php

declare(strict_types=1);

namespace App\Tests\Api\Entity;

use App\Tests\AbstractApiTestCase;

/**
 * @internal
 */
class MachineProductLinkTest extends AbstractApiTestCase
{
    public function testGetCollection(): void
    {
        $machine = $this->createMachine('Machine A');
        $product = $this->createProduct('Produit A');
        $this->createMachineProductLink($machine, $product);

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

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

    public function testPost(): void
    {
        $machine = $this->createMachine('Machine A');
        $product = $this->createProduct('Produit A');

        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/machine_product_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine' => self::iri('machines', $machine->getId()),
                'product' => self::iri('products', $product->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
    }

    public function testPostWithParentComponentLink(): void
    {
        $machine   = $this->createMachine('Machine A');
        $composant = $this->createComposant('Pompe');
        $product   = $this->createProduct('Produit A');
        $compLink  = $this->createMachineComponentLink($machine, $composant);

        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/machine_product_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine'             => self::iri('machines', $machine->getId()),
                'product'             => self::iri('products', $product->getId()),
                'parentComponentLink' => self::iri('machine_component_links', $compLink->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
    }

    public function testPostWithParentPieceLink(): void
    {
        $machine = $this->createMachine('Machine A');
        $piece   = $this->createPiece('Joint');
        $product = $this->createProduct('Produit A');
        $plLink  = $this->createMachinePieceLink($machine, $piece);

        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/machine_product_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine'         => self::iri('machines', $machine->getId()),
                'product'         => self::iri('products', $product->getId()),
                'parentPieceLink' => self::iri('machine_piece_links', $plLink->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
    }

    public function testDelete(): void
    {
        $machine = $this->createMachine('Machine A');
        $product = $this->createProduct('Produit A');
        $link    = $this->createMachineProductLink($machine, $product);

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

        $this->assertResponseStatusCodeSame(204);
    }

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

        $this->assertResponseStatusCodeSame(401);
    }

    public function testViewerCannotWrite(): void
    {
        $machine = $this->createMachine('Machine A');
        $product = $this->createProduct('Produit A');

        $client = $this->createViewerClient();
        $client->request('POST', '/api/machine_product_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine' => self::iri('machines', $machine->getId()),
                'product' => self::iri('products', $product->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(403);
    }
}
