/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
/**
 * Runtime domain model for the Datalayer Client.
 *
 * @module models/RuntimeDTO
 */
import { updateRuntime } from '../api/runtimes/runtimes.js';
import { validateJSON } from '../api/utils/validation.js';
/**
 * Runtime domain model that wraps API responses with convenient methods.
 * Provides state management and lifecycle operations for computational runtimes.
 *
 * @example
 * ```typescript
 * const runtime = await client.createRuntime({ environment_name: 'python-cpu' });
 * await runtime.waitUntilReady();
 * ```
 */
export class RuntimeDTO {
    /** @internal */
    _data;
    _client;
    _deleted = false;
    /**
     * Create a Runtime instance.
     *
     * @param data - Runtime data from API
     * @param client - Client instance
     */
    constructor(data, client) {
        this._data = data;
        this._client = client;
    }
    // ========================================================================
    // Helper Methods
    // ========================================================================
    /**
     * Check if this runtime has been deleted and throw error if so.
     * @throws Error if deleted
     */
    _checkDeleted() {
        if (this._deleted) {
            throw new Error(`Runtime ${this._data.pod_name} has been deleted and no longer exists`);
        }
    }
    // ========================================================================
    // Static Properties (set at creation, never change)
    // ========================================================================
    /** Kubernetes pod name for the runtime instance. */
    get podName() {
        this._checkDeleted();
        return this._data.pod_name;
    }
    /** Unique identifier for the runtime. */
    get uid() {
        this._checkDeleted();
        return this._data.uid;
    }
    /** Name of the environment this runtime is based on. */
    get environmentName() {
        this._checkDeleted();
        return this._data.environment_name;
    }
    /** Ingress URL for accessing the runtime. */
    get ingress() {
        this._checkDeleted();
        return this._data.ingress;
    }
    /** Authentication token for accessing the runtime. */
    get token() {
        this._checkDeleted();
        return this._data.token;
    }
    /** Credits consumed per second. */
    get burningRate() {
        this._checkDeleted();
        return this._data.burning_rate;
    }
    /** User-friendly name for the runtime. */
    get givenName() {
        this._checkDeleted();
        return this._data.given_name;
    }
    /** Type of runtime (notebook, terminal, or job). */
    get type() {
        this._checkDeleted();
        return this._data.type;
    }
    /** When the runtime started. */
    get startedAt() {
        this._checkDeleted();
        return new Date(Number(this._data.started_at) * 1000);
    }
    /** When the runtime will expire. */
    get expiredAt() {
        this._checkDeleted();
        return new Date(Number(this._data.expired_at) * 1000);
    }
    /** Environment title for display. */
    get environmentTitle() {
        this._checkDeleted();
        return this._data.environment_title || '';
    }
    // ========================================================================
    // Action Methods
    // ========================================================================
    /**
     * Delete this runtime permanently.
     * After deletion, subsequent calls to dynamic methods will throw errors.
     */
    async delete() {
        await this._client.deleteRuntime(this.podName);
        this._deleted = true;
    }
    /**
     * Update runtime from a snapshot.
     *
     * @param from - Snapshot identifier to restore from
     * @returns Updated Runtime instance
     */
    async update(from) {
        this._checkDeleted();
        const updated = await updateRuntime(this._client.getToken(), this.podName, from, this._client.getRuntimesRunUrl());
        return new RuntimeDTO(updated, this._client);
    }
    /**
     * Create a snapshot of this runtime.
     *
     * @param name - Name for the snapshot
     * @param description - Optional description
     * @param stop - Whether to stop runtime after snapshotting
     * @returns Created Snapshot instance
     */
    async createSnapshot(name, description, stop) {
        this._checkDeleted();
        return await this._client.createSnapshot(this.podName, name, description, stop);
    }
    // ========================================================================
    // Utility Methods
    // ========================================================================
    /**
     * Get runtime data in camelCase format.
     * Returns only the core fields that consumers need.
     * This provides a stable interface regardless of API changes.
     * Returns the current cached state - call getState() first if you need fresh data.
     *
     * @returns Core runtime data with camelCase properties
     */
    toJSON() {
        this._checkDeleted();
        // Safely convert dates to ISO strings, handling invalid dates
        const safeToISO = (date) => {
            try {
                const iso = date.toISOString();
                return iso;
            }
            catch {
                // If date is invalid, return empty string or current time
                return new Date().toISOString();
            }
        };
        const obj = {
            // Core identifiers
            uid: this.uid,
            podName: this.podName,
            givenName: this.givenName,
            // Environment info
            environmentName: this.environmentName,
            environmentTitle: this.environmentTitle,
            // State and type
            type: this.type,
            // Burning
            burningRate: this.burningRate,
            // URLs and tokens
            // FIXME: Consider renaming? jupyterServerUrl and jupyterServerToken
            ingress: this.ingress,
            token: this.token,
            // Timing
            startedAt: safeToISO(this.startedAt),
            expiredAt: safeToISO(this.expiredAt),
        };
        validateJSON(obj, 'Runtime');
        return obj;
    }
    /**
     * Get the raw runtime data exactly as received from the API.
     * This preserves the original snake_case naming from the API response.
     * Returns the current cached state - call getState() first if you need fresh data.
     *
     * @returns Raw runtime data from API
     */
    rawData() {
        this._checkDeleted();
        return this._data;
    }
    /** String representation of the runtime. */
    toString() {
        this._checkDeleted();
        return `Runtime(${this.podName}, ${this.environmentName})`;
    }
}
