<?php

app_require('classes/edge_gateway_manager.php');

use classes\edge_gateway_manager;

it('caps install-session diagnostics and events while preserving the first start timestamp', function (): void {
    $session = [];

    for ($index = 1; $index <= 14; $index += 1) {
        $session = edge_gateway_manager::mergeInstallSessionUpdate($session, [
            'status' => edge_gateway_manager::INSTALL_SESSION_STATUS_RUNNING,
            'step' => 'STEP_' . $index,
            'message' => 'Installer phase ' . $index,
        ], strtotime('2026-04-08 10:00:' . str_pad((string)$index, 2, '0', STR_PAD_LEFT)));
    }

    $failed = edge_gateway_manager::mergeInstallSessionUpdate($session, [
        'status' => edge_gateway_manager::INSTALL_SESSION_STATUS_FAILED,
        'step' => 'START_STACK',
        'message' => 'Compose rollout failed during startup.',
        'diagnostics' => array_map(
            static fn(int $index): array => [
                'name' => 'Diagnostic ' . $index,
                'output' => 'Output ' . $index,
            ],
            range(1, 8)
        ),
    ], strtotime('2026-04-08 10:01:30'));

    expect($failed['status'])->toBe(edge_gateway_manager::INSTALL_SESSION_STATUS_FAILED);
    expect($failed['step'])->toBe('START_STACK');
    expect($failed['message'])->toBe('Compose rollout failed during startup.');
    expect($failed['started_at'])->toBe('2026-04-08 10:00:01');
    expect($failed['updated_at'])->toBe('2026-04-08 10:01:30');
    expect($failed['last_error'])->toBe('Compose rollout failed during startup.');
    expect($failed['diagnostics'])->toHaveCount(6);
    expect($failed['diagnostics'][0]['name'])->toBe('Diagnostic 3');
    expect($failed['diagnostics'][5]['name'])->toBe('Diagnostic 8');
    expect($failed['events'])->toHaveCount(12);
    expect($failed['events'][11]['status'])->toBe(edge_gateway_manager::INSTALL_SESSION_STATUS_FAILED);
    expect($failed['events'][11]['step'])->toBe('START_STACK');
});

it('clears terminal failure details after a successful claim update', function (): void {
    $claimed = edge_gateway_manager::mergeInstallSessionUpdate([
        'status' => edge_gateway_manager::INSTALL_SESSION_STATUS_FAILED,
        'step' => 'START_STACK',
        'message' => 'Compose rollout failed during startup.',
        'started_at' => '2026-04-08 10:00:01',
        'updated_at' => '2026-04-08 10:01:30',
        'last_error' => 'Compose rollout failed during startup.',
        'diagnostics' => [
            ['name' => 'systemctl status', 'output' => 'failed'],
        ],
        'events' => [
            [
                'status' => edge_gateway_manager::INSTALL_SESSION_STATUS_FAILED,
                'step' => 'START_STACK',
                'message' => 'Compose rollout failed during startup.',
                'at' => '2026-04-08 10:01:30',
            ],
        ],
    ], [
        'status' => edge_gateway_manager::INSTALL_SESSION_STATUS_CLAIMED,
        'step' => edge_gateway_manager::INSTALL_SESSION_STATUS_CLAIMED,
        'message' => 'Gateway claimed successfully.',
        'gateway_id' => 703,
    ], strtotime('2026-04-08 10:02:00'));

    expect($claimed['status'])->toBe(edge_gateway_manager::INSTALL_SESSION_STATUS_CLAIMED);
    expect($claimed['gateway_id'])->toBe(703);
    expect($claimed['last_error'])->toBeNull();
    expect($claimed['diagnostics'])->toBe([]);
    expect($claimed['events'])->toHaveCount(2);
    expect($claimed['events'][1]['status'])->toBe(edge_gateway_manager::INSTALL_SESSION_STATUS_CLAIMED);
});

it('marks expired non-terminal install sessions as terminal when read back', function (): void {
    $normalized = edge_gateway_manager::normalizeInstallSessionRecord([
        'status' => edge_gateway_manager::INSTALL_SESSION_STATUS_RUNNING,
        'step' => 'WAIT_FOR_CLAIM',
        'message' => 'Installer is waiting for the gateway heartbeat and claim.',
        'started_at' => '2026-04-08 10:00:01',
        'updated_at' => '2026-04-08 10:01:30',
    ], '2026-04-08 10:01:00', strtotime('2026-04-08 10:02:00'));

    expect($normalized['status'])->toBe(edge_gateway_manager::INSTALL_SESSION_STATUS_EXPIRED);
    expect($normalized['step'])->toBe('WAIT_FOR_CLAIM');
    expect($normalized['updated_at'])->toBe('2026-04-08 10:01:30');
    expect($normalized['message'])->toBe('Installer is waiting for the gateway heartbeat and claim.');
    expect($normalized['last_error'])->toBe('Install token expired.');
    expect($normalized['terminal'])->toBeTrue();
});
