/*
 * Copyright (c) 2023-2025 Datalayer, Inc.
 * Distributed under the terms of the Modified BSD License.
 */
import * as items from '../api/spacer/items.js';
/**
 * Abstract base class for all Datalayer content items.
 * Provides common functionality for content management including lifecycle tracking.
 *
 * @template TData - Raw data type from API
 * @template TUpdateRequest - Update request type for API
 */
export class ItemDTO {
    _data;
    _client;
    _deleted = false;
    /**
     * Create an Item instance.
     * @param data - Item data from API
     * @param client - Client instance
     */
    constructor(data, client) {
        this._data = data;
        this._client = client;
    }
    // ========================================================================
    // Deletion State Management
    // ========================================================================
    /** Check if this item has been deleted. */
    get isDeleted() {
        return this._deleted;
    }
    /**
     * Check if this item has been deleted and throw error if so.
     * @throws Error if deleted
     */
    _checkDeleted() {
        if (this._deleted) {
            throw new Error(`${this.constructor.name} ${this._data.id} has been deleted and no longer exists`);
        }
    }
    // ========================================================================
    // Static Properties (set at creation, never change)
    // ========================================================================
    /** Item ID. */
    get id() {
        this._checkDeleted();
        return this._data.id;
    }
    /** Unique identifier for the item. */
    get uid() {
        this._checkDeleted();
        return this._data.uid;
    }
    /** Parent space ID. */
    get spaceId() {
        this._checkDeleted();
        // Try the direct field first (if API provides it)
        if (this._data.space_id) {
            return this._data.space_id;
        }
        // Extract from s3_path_s if available: "datalayer.ai/SPACE_ID/..."
        const s3Path = this._data.s3_path_s;
        if (s3Path && typeof s3Path === 'string') {
            const match = s3Path.match(/^datalayer\.app\/([^/]+)\//);
            if (match) {
                return match[1];
            }
        }
        // Fallback to empty string if no space ID can be determined
        return '';
    }
    /** Owner user ID. */
    get ownerId() {
        this._checkDeleted();
        return (this._data.owner_id || this._data.creator_uid || '');
    }
    /** When the item was created. */
    get createdAt() {
        this._checkDeleted();
        const dateStr = this._data.creation_ts_dt || this._data.created_at;
        if (!dateStr) {
            throw new Error(`No creation timestamp available for ${this.constructor.name.toLowerCase()}`);
        }
        return new Date(dateStr);
    }
    /** The cached update time. */
    get updatedAt() {
        this._checkDeleted();
        const dateStr = this._data.last_update_ts_dt ||
            this._data.updated_at ||
            this._data.creation_ts_dt ||
            this._data.created_at;
        if (!dateStr) {
            throw new Error(`No update timestamp available for ${this.constructor.name.toLowerCase()}`);
        }
        return new Date(dateStr);
    }
    // ========================================================================
    // Action Methods
    // ========================================================================
    /**
     * Delete this item permanently.
     * After deletion, all subsequent method calls will throw errors.
     */
    async delete() {
        this._checkDeleted();
        const token = this._client.getToken();
        const spacerRunUrl = this._client.getSpacerRunUrl();
        await items.deleteItem(token, this.uid, spacerRunUrl);
        this._deleted = true;
    }
    /** Get the document content from API. */
    async getContent() {
        this._checkDeleted();
        // First try: CDN URL (fastest)
        const cdnUrl = this._data.cdn_url_s;
        if (cdnUrl) {
            try {
                const response = await fetch(cdnUrl);
                if (!response.ok) {
                    throw new Error('Failed to fetch content from CDN');
                }
                const data = await response.json();
                if (data.content !== undefined && data.content !== null) {
                    return data.content;
                }
            }
            catch (error) {
                console.error('Error fetching content from CDN:', error);
            }
        }
        // Second try: Check if content is already loaded
        const cachedContent = this.content;
        if (cachedContent !== undefined && cachedContent !== null) {
            return cachedContent;
        }
        // Third try: Fetch full item details from API
        try {
            const token = this._client.getToken();
            const spacerRunUrl = this._client.getSpacerRunUrl();
            const response = await items.getItem(token, this.uid, spacerRunUrl);
            // Update internal data with full item details
            if (response.success && response.item) {
                this._data = response.item;
                const freshContent = this.content;
                if (freshContent !== undefined && freshContent !== null) {
                    return freshContent;
                }
            }
        }
        catch (error) {
            console.error('Error fetching full item details:', error);
        }
        throw new Error(`Content is not available for item ${this.uid}. The item may not have been fully loaded or the content is not yet available.`);
    }
    // ========================================================================
    // Utility Methods
    // ========================================================================
    /** Get raw item data object. */
    rawData() {
        this._checkDeleted();
        return this._data;
    }
    /** String representation of the item. */
    toString() {
        this._checkDeleted();
        const name = this.name || 'Unnamed';
        return `${this.constructor.name}(${this.id}, ${name})`;
    }
    // ========================================================================
    // Protected Helper Methods
    // ========================================================================
    /** Get Client token for API calls. */
    _getToken() {
        return this._client.getToken();
    }
    /** Get spacer API URL for API calls. */
    _getSpacerRunUrl() {
        return this._client.getSpacerRunUrl();
    }
    /** Update internal data after API call. */
    _updateData(newData) {
        this._data = newData;
    }
}
