/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
/**
 * Runtime checkpoints API functions for the Datalayer platform.
 *
 * Provides functions for managing CRIU full-pod checkpoints.
 * These are distinct from runtime snapshots (Jupyter sandbox snapshots).
 *
 * @module api/runtimes/checkpoints
 */
import { requestDatalayerAPI } from '../DatalayerApi.js';
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
import { validateToken, validateRequiredString } from '../utils/validation.js';
// ─── API Functions ─────────────────────────────────────────────────────────
/**
 * List runtime checkpoints for a specific runtime.
 * @param token - Authentication token
 * @param baseUrl - Base URL for the runtimes API
 * @param runtimeUid - Runtime UID to list checkpoints for
 * @returns Promise resolving to list of checkpoints
 */
export const listCheckpoints = async (token, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES, runtimeUid) => {
    validateToken(token);
    if (!runtimeUid) {
        throw new Error('runtimeUid is required to list checkpoints');
    }
    return requestDatalayerAPI({
        url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-checkpoints/${encodeURIComponent(runtimeUid)}`,
        method: 'GET',
        token,
    });
};
/**
 * Get a single runtime checkpoint by ID.
 * @param token - Authentication token
 * @param runtimeUid - The runtime UID
 * @param checkpointId - The checkpoint ID (ULID)
 * @param baseUrl - Base URL for the runtimes API
 * @returns Promise resolving to checkpoint details
 */
export const getCheckpoint = async (token, runtimeUid, checkpointId, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
    validateToken(token);
    validateRequiredString(runtimeUid, 'Runtime UID');
    validateRequiredString(checkpointId, 'Checkpoint ID');
    return requestDatalayerAPI({
        url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-checkpoints/${encodeURIComponent(runtimeUid)}/${checkpointId}`,
        method: 'GET',
        token,
    });
};
/**
 * Create a checkpoint record (after a CRIU checkpoint has been taken).
 * @param token - Authentication token
 * @param data - Checkpoint creation payload (runtime_uid, agentspec, etc.)
 * @param baseUrl - Base URL for the runtimes API
 * @returns Promise resolving to the created checkpoint
 */
export const createCheckpoint = async (token, data, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
    validateToken(token);
    return requestDatalayerAPI({
        url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-checkpoints`,
        method: 'POST',
        token,
        body: data,
    });
};
/**
 * Poll a checkpoint until it reaches one of the target statuses.
 *
 * Useful for waiting until an async pause (status "paused")
 * completes before proceeding.  Checkpoint status stays "paused"
 * during resume — only the agent runtime status transitions.
 *
 * @param token - Authentication token
 * @param runtimeUid - The runtime UID that owns the checkpoint
 * @param checkpointId - The checkpoint ID (ULID) to poll
 * @param targetStatuses - Set of statuses that signal completion (e.g. ["paused", "failed"])
 * @param baseUrl - Base URL for the runtimes API
 * @param intervalMs - Polling interval in milliseconds (default: 2000)
 * @param timeoutMs - Maximum wait time in milliseconds (default: 600000 = 10 min)
 * @returns Promise resolving to the checkpoint data once a target status is reached
 * @throws {Error} If polling times out or the request fails
 */
export const waitForCheckpointStatus = async (token, runtimeUid, checkpointId, targetStatuses, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES, intervalMs = 2000, timeoutMs = 600_000) => {
    validateToken(token);
    validateRequiredString(runtimeUid, 'Runtime UID');
    validateRequiredString(checkpointId, 'Checkpoint ID');
    const deadline = Date.now() + timeoutMs;
    while (Date.now() < deadline) {
        const resp = await getCheckpoint(token, runtimeUid, checkpointId, baseUrl);
        if (targetStatuses.includes(resp.checkpoint.status)) {
            return resp.checkpoint;
        }
        // Wait before next poll
        await new Promise(resolve => setTimeout(resolve, intervalMs));
    }
    throw new Error(`Checkpoint ${checkpointId} did not reach status [${targetStatuses.join(', ')}] within ${timeoutMs / 1000}s`);
};
/**
 * Delete a runtime checkpoint.
 * @param token - Authentication token
 * @param runtimeUid - The runtime UID that owns the checkpoint
 * @param checkpointId - The checkpoint ID (ULID) to delete
 * @param baseUrl - Base URL for the runtimes API
 * @returns Promise resolving when deletion is complete
 */
export const deleteCheckpoint = async (token, runtimeUid, checkpointId, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
    validateToken(token);
    validateRequiredString(runtimeUid, 'Runtime UID');
    validateRequiredString(checkpointId, 'Checkpoint ID');
    return requestDatalayerAPI({
        url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-checkpoints/${encodeURIComponent(runtimeUid)}/${checkpointId}`,
        method: 'DELETE',
        token,
    });
};
