<?php

declare(strict_types=1);

namespace App\Tests\Api\Entity;

use App\Tests\AbstractApiTestCase;

/**
 * @internal
 */
class MachinePieceLinkTest extends AbstractApiTestCase
{
    public function testGetCollection(): void
    {
        $machine = $this->createMachine('Machine A');
        $piece   = $this->createPiece('Joint A');
        $this->createMachinePieceLink($machine, $piece);

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

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

    public function testPost(): void
    {
        $machine = $this->createMachine('Machine A');
        $piece   = $this->createPiece('Joint A');

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

        $this->assertResponseStatusCodeSame(201);
    }

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

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

        $this->assertResponseStatusCodeSame(201);
    }

    public function testPostWithOverrides(): void
    {
        $machine = $this->createMachine('Machine A');
        $piece   = $this->createPiece('Joint A');

        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/machine_piece_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine'      => self::iri('machines', $machine->getId()),
                'piece'        => self::iri('pieces', $piece->getId()),
                'nameOverride' => 'Joint spécial',
                'prixOverride' => '25.00',
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
        $this->assertJsonContains([
            'nameOverride' => 'Joint spécial',
            'prixOverride' => '25.00',
        ]);
    }

    public function testPostWithQuantity(): void
    {
        $client  = $this->createGestionnaireClient();
        $machine = $this->createMachine();
        $piece   = $this->createPiece();

        $client->request('POST', '/api/machine_piece_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine'  => self::iri('machines', $machine->getId()),
                'piece'    => self::iri('pieces', $piece->getId()),
                'quantity' => 5,
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
        $this->assertJsonContains(['quantity' => 5]);
    }

    public function testPostDefaultQuantity(): void
    {
        $client  = $this->createGestionnaireClient();
        $machine = $this->createMachine();
        $piece   = $this->createPiece();

        $client->request('POST', '/api/machine_piece_links', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'machine' => self::iri('machines', $machine->getId()),
                'piece'   => self::iri('pieces', $piece->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
        $this->assertJsonContains(['quantity' => 1]);
    }

    public function testDelete(): void
    {
        $machine = $this->createMachine('Machine A');
        $piece   = $this->createPiece('Joint A');
        $link    = $this->createMachinePieceLink($machine, $piece);

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

        $this->assertResponseStatusCodeSame(204);
    }

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

        $this->assertResponseStatusCodeSame(401);
    }

    public function testViewerCannotWrite(): void
    {
        $machine = $this->createMachine('Machine A');
        $piece   = $this->createPiece('Joint A');

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

        $this->assertResponseStatusCodeSame(403);
    }
}
