<?php

declare(strict_types=1);

usesApiSuite();

it('returns the updated lane id after editing a scanner whose null lane was already cached', function (): void {
    api_test_covers('PUT /numberplatescanners', 'happy');

    $department = api_fixtures()->createDepartment([
        'name' => 'Scanner Department ' . uniqid('', false),
    ]);
    $session = api_fixtures()->createUserSession([
        'add_department_lane',
        'add_number_plate_scanner',
        'edit_number_plate_scanner',
        'department_access_' . (int)$department['id'],
    ]);

    $laneName = 'Lane ' . uniqid('', false);
    $laneResponse = api_client()->post('/department/lanes', [
        'department' => $department['id'],
        'name' => $laneName,
    ], $session['headers']);

    $laneResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess();

    $lane = api_test_runtime()->queryOne(
        "SELECT id FROM department_lanes WHERE department = " . (int)$department['id'] .
        " AND name = '" . api_test_runtime()->db()->real_escape_string($laneName) . "'" .
        ' ORDER BY id DESC LIMIT 1'
    );

    expect($lane)->not->toBeNull();
    $laneId = (int)($lane['id'] ?? 0);
    expect($laneId)->toBeGreaterThan(0);
    api_fixtures()->cleanupDeleteById('department_lanes', $laneId);

    $scannerName = 'Scanner ' . uniqid('', false);
    $createResponse = api_client()->post('/numberplatescanners', [
        'department_id' => $department['id'],
        'name' => $scannerName,
        'notes' => 'Original notes',
    ], $session['headers']);

    $createResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess()
        ->assertMessage('Number plate scanner added');

    $createdScanner = api_test_runtime()->queryOne(
        "SELECT id FROM plate_scanners WHERE department_id = " . (int)$department['id'] .
        " AND name = '" . api_test_runtime()->db()->real_escape_string($scannerName) . "'" .
        ' ORDER BY id DESC LIMIT 1'
    );

    expect($createdScanner)->not->toBeNull();
    $scannerId = (int)($createdScanner['id'] ?? 0);
    expect($scannerId)->toBeGreaterThan(0);
    api_fixtures()->cleanupDeleteById('plate_scanners', $scannerId);

    $redis = api_test_runtime()->redis();
    expect($redis)->not->toBeNull();
    $cacheKeys = [
        "obj_prop:plate_scanners:{$scannerId}:lane_id" => '___NULL___',
        "obj_prop:plate_scanners:{$scannerId}:name" => $scannerName,
        "obj_prop:plate_scanners:{$scannerId}:notes" => 'Original notes',
    ];
    foreach ($cacheKeys as $cacheKey => $value) {
        $redis->set($cacheKey, $value);
    }

    $updateResponse = api_client()->put('/numberplatescanners', [
        'id' => $scannerId,
        'department_id' => $department['id'],
        'lane_id' => $laneId,
        'name' => 'Updated scanner',
        'notes' => 'Updated notes',
    ], $session['headers']);

    $updateResponse
        ->assertStatus(200)
        ->assertEnvelope()
        ->assertSuccess()
        ->assertMessage('Number plate scanner edited');

    $redis->del(array_keys($cacheKeys));

    $updatedScanner = $updateResponse->data()['scanner'] ?? null;
    expect($updatedScanner)->toBeArray();
    expect($updatedScanner['id'] ?? null)->toBe($scannerId);
    expect($updatedScanner['department_id'] ?? null)->toBe($department['id']);
    expect($updatedScanner['lane_id'] ?? null)->toBe($laneId);
    expect($updatedScanner['name'] ?? null)->toBe('Updated scanner');
    expect($updatedScanner['notes'] ?? null)->toBe('Updated notes');

    $row = api_fixtures()->fetchRowById('plate_scanners', $scannerId);

    expect($row)->not->toBeNull();
    expect((int)($row['lane_id'] ?? 0))->toBe($laneId);
    expect($row['name'] ?? null)->toBe('Updated scanner');
    expect($row['notes'] ?? null)->toBe('Updated notes');
});

it('rejects plate scanner edits when the permission is missing', function (): void {
    api_test_covers('PUT /numberplatescanners', 'auth');

    $session = api_fixtures()->createUserSession([]);

    $response = api_client()->put('/numberplatescanners', [
        'id' => 1,
        'department_id' => 1,
        'name' => 'No permission',
        'notes' => 'Should fail',
    ], $session['headers']);

    $response
        ->assertStatus(403)
        ->assertEnvelope()
        ->assertSuccess(false)
        ->assertMissingPermissions(['edit_number_plate_scanner']);
});
