<?php

declare(strict_types=1);

namespace App\Tests\Api\Controller;

use App\Tests\AbstractApiTestCase;

/**
 * @internal
 */
class MachineCustomFieldDefinitionTest extends AbstractApiTestCase
{
    public function testCreateCustomFieldForMachine(): void
    {
        $machine = $this->createMachine('Machine CF Create');

        $client = $this->createGestionnaireClient();
        $client->request('POST', '/api/custom_fields', [
            'headers' => ['Content-Type' => 'application/ld+json'],
            'json'    => [
                'name'    => 'Tension',
                'type'    => 'number',
                'machine' => self::iri('machines', $machine->getId()),
            ],
        ]);

        $this->assertResponseStatusCodeSame(201);
        $this->assertJsonContains(['name' => 'Tension', 'type' => 'number']);

        // Verify via structure endpoint
        $client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
        $this->assertResponseIsSuccessful();

        $data = $client->getResponse()->toArray();
        $this->assertArrayHasKey('customFields', $data['machine']);
        $this->assertNotEmpty($data['machine']['customFields'], 'customFields should contain the new field');

        $found = false;
        foreach ($data['machine']['customFields'] as $cf) {
            if ('Tension' === $cf['name'] && 'number' === $cf['type']) {
                $found = true;

                break;
            }
        }
        $this->assertTrue($found, 'Structure should contain the created custom field "Tension"');
    }

    public function testUpdateCustomFieldForMachine(): void
    {
        $machine = $this->createMachine('Machine CF Update');
        $cf      = $this->createCustomField('OldName', 'text', $machine);

        $client = $this->createGestionnaireClient();
        $client->request('PATCH', self::iri('custom_fields', $cf->getId()), [
            'headers' => ['Content-Type' => 'application/merge-patch+json'],
            'json'    => ['name' => 'NewName'],
        ]);

        $this->assertResponseIsSuccessful();
        $this->assertJsonContains(['name' => 'NewName']);

        // Verify via structure endpoint
        $client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
        $this->assertResponseIsSuccessful();

        $data = $client->getResponse()->toArray();
        $this->assertNotEmpty($data['machine']['customFields']);

        $names = array_column($data['machine']['customFields'], 'name');
        $this->assertContains('NewName', $names, 'Structure should reflect the updated custom field name');
        $this->assertNotContains('OldName', $names, 'Old name should no longer appear');
    }

    public function testDeleteCustomFieldForMachine(): void
    {
        $machine = $this->createMachine('Machine CF Delete');
        $cf      = $this->createCustomField('ToDelete', 'text', $machine);

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

        $this->assertResponseStatusCodeSame(204);

        // Verify via structure endpoint
        $client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
        $this->assertResponseIsSuccessful();

        $data = $client->getResponse()->toArray();
        $this->assertSame([], $data['machine']['customFields'], 'customFields should be empty after deletion');
    }

    public function testAddCustomFieldsEndpointInitializesValues(): void
    {
        $machine = $this->createMachine('Machine CF Values');
        $cf      = $this->createCustomField('Voltage', 'number', $machine);
        $cf->setDefaultValue('220');
        $em = $this->getEntityManager();
        $em->persist($cf);
        $em->flush();

        $client = $this->createGestionnaireClient();
        $client->request('POST', sprintf('/api/machines/%s/add-custom-fields', $machine->getId()));

        $this->assertResponseIsSuccessful();
        $response = $client->getResponse()->toArray();
        $this->assertTrue($response['success']);
        $this->assertNotEmpty($response['customFieldValues'], 'customFieldValues should not be empty after add-custom-fields');

        // Verify via structure endpoint
        $client->request('GET', sprintf('/api/machines/%s/structure', $machine->getId()));
        $this->assertResponseIsSuccessful();

        $data = $client->getResponse()->toArray();
        $this->assertNotEmpty($data['machine']['customFieldValues'], 'Structure should contain initialized custom field values');

        $cfv = $data['machine']['customFieldValues'][0];
        $this->assertSame('220', $cfv['value'], 'Value should match the default value');
        $this->assertSame('Voltage', $cfv['customField']['name']);
    }
}
