<?php

it('serializes self-serve session synchronization before reading or creating open sessions', function (): void {
    $washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));

    expect($washFlow)->not->toBeFalse()
        ->and($washFlow)->toContain('withSessionMutationLock')
        ->and($washFlow)->toContain('sessionMutationLockKey')
        ->and($washFlow)->toContain('set_if_absent_with_expiration')
        ->and($washFlow)->toContain('GET_LOCK');

    $syncOffset = strpos($washFlow, 'public function synchronizeSession');
    expect($syncOffset)->not->toBeFalse();

    $syncMethod = substr($washFlow, (int)$syncOffset, 9000);
    $snapshotOffset = strpos($syncMethod, '$snapshot = $this->buildEligibilitySnapshot');
    $lockOffset = strpos($syncMethod, '$mutationResult = $this->withSessionMutationLock');
    $findOffset = strpos($syncMethod, '$session = $this->findLatestOpenSession');
    $addOffset = strpos($syncMethod, '$session = (new selfserve_wash_sessions_o())->add');
    $relayOffset = strpos($syncMethod, '$this->syncMachineRelayFromVisibleServices');

    expect($snapshotOffset)->not->toBeFalse()
        ->and($lockOffset)->not->toBeFalse()
        ->and($findOffset)->not->toBeFalse()
        ->and($addOffset)->not->toBeFalse()
        ->and($relayOffset)->not->toBeFalse()
        ->and($snapshotOffset)->toBeLessThan($lockOffset)
        ->and($lockOffset)->toBeLessThan($findOffset)
        ->and($findOffset)->toBeLessThan($addOffset)
        ->and($addOffset)->toBeLessThan($relayOffset);
});

it('closes self-serve wash sessions with an atomic open-session guard', function (): void {
    $sessionObject = file_get_contents(app_path('objects/selfserve_wash_sessions_o.php'));
    $washFlow = file_get_contents(app_path('modules/selfserve/classes/selfserve_wash_flow.php'));

    expect($sessionObject)->not->toBeFalse()
        ->and($sessionObject)->toContain('markCompletedIfOpen')
        ->and($sessionObject)->toContain('markForceStoppedIfOpen')
        ->and($sessionObject)->toContain('AND `completed_at` IS NULL')
        ->and($sessionObject)->toContain('AND UPPER(TRIM(`status`)) NOT IN ($terminalStatuses)');

    expect($washFlow)->not->toBeFalse()
        ->and($washFlow)->toContain('if (!$session->markCompletedIfOpen($orderId))')
        ->and($washFlow)->toContain('if (!$session->markForceStoppedIfOpen($orderId, $eventPayload))');
});
