File snapshots-module.js of Package PersistenceOS

/**
 * PersistenceOS Snapshots Management Module
 * Handles snapshot creation, scheduling, and management functionality
 * 
 * Depends on: core-utils.js, auth-module.js
 */

// =============================================================================
// SNAPSHOTS STATE MANAGEMENT
// =============================================================================

const snapshotsState = {
    systemSnapshots: [
        { name: 'system-2023-06-15', type: 'System', date: '2023-06-15 10:30', size: '2.5 GB' },
        { name: 'vm-ubuntu-2023-06-14', type: 'VM', date: '2023-06-14 14:45', size: '4.2 GB' }
    ],
    isRefreshing: false,
    refreshInterval: null,
    lastUpdate: null
};

// =============================================================================
// SNAPSHOT DATA FUNCTIONS
// =============================================================================

/**
 * Refresh snapshots data from API
 * @returns {Promise<void>}
 */
async function refreshSnapshots() {
    snapshotsState.isRefreshing = true;
    console.log('🔄 Refreshing snapshots data...');
    
    try {
        const [systemResponse, storageResponse] = await Promise.all([
            PersistenceCore.apiGet('/snapshots/system'),
            PersistenceCore.apiGet('/snapshots/storage')
        ]);
        
        // Combine system and storage snapshots
        snapshotsState.systemSnapshots = [
            ...systemResponse.snapshots.map(s => ({ ...s, category: 'system' })),
            ...storageResponse.snapshots.map(s => ({ ...s, category: 'storage' }))
        ];
        
        console.log(`✅ Loaded ${snapshotsState.systemSnapshots.length} snapshots`);
        PersistenceCore.showNotification('✅ Snapshots refreshed successfully', 'success');
        
        snapshotsState.lastUpdate = new Date();
        
        // Trigger custom event for Vue.js reactivity
        window.dispatchEvent(new CustomEvent('snapshots-data-updated', {
            detail: { snapshots: snapshotsState.systemSnapshots, stats: getSnapshotStats() }
        }));
        
    } catch (error) {
        console.error('❌ Error refreshing snapshots:', error);
        PersistenceCore.showNotification('❌ Failed to refresh snapshots', 'error');
    } finally {
        snapshotsState.isRefreshing = false;
    }
}

/**
 * Get snapshot statistics
 * @returns {object}
 */
function getSnapshotStats() {
    const snapshots = snapshotsState.systemSnapshots || [];
    
    return {
        total: snapshots.length,
        recent: snapshots.filter(s => {
            const created = new Date(s.created || s.date);
            const now = new Date();
            const daysDiff = (now - created) / (1000 * 60 * 60 * 24);
            return daysDiff <= 7;
        }).length,
        scheduled: snapshots.filter(s => s.isScheduled).length,
        failed: snapshots.filter(s => s.status === 'failed').length,
        system: snapshots.filter(s => s.category === 'system').length,
        storage: snapshots.filter(s => s.category === 'storage').length
    };
}

// =============================================================================
// SNAPSHOT OPERATIONS
// =============================================================================

/**
 * Create new snapshot
 * @returns {Promise<void>}
 */
async function createSnapshot() {
    console.log('📸 Creating new snapshot...');
    
    // Show snapshot creation modal
    const snapshotType = await showSnapshotCreationModal();
    if (!snapshotType) return;
    
    try {
        const response = await PersistenceCore.apiPost('/snapshots/create', {
            name: `snapshot-${Date.now()}`,
            description: 'Manual snapshot created from UI',
            type: snapshotType
        });
        
        PersistenceCore.showNotification('✅ Snapshot created successfully', 'success');
        await refreshSnapshots();
        
    } catch (error) {
        console.error('❌ Error creating snapshot:', error);
        
        // Get detailed error information
        const errorMessage = error.message || 'Unknown error';
        PersistenceCore.showNotification(`❌ Snapshot failed: ${errorMessage}`, 'error');
    }
}

/**
 * Schedule snapshot creation
 * @returns {Promise<void>}
 */
async function scheduleSnapshot() {
    console.log('⏰ Opening snapshot scheduling...');
    
    // Show snapshot scheduling modal
    const scheduleConfig = await showSnapshotScheduleModal();
    if (!scheduleConfig) return;
    
    try {
        await PersistenceCore.apiPost('/snapshots/schedule', scheduleConfig);
        PersistenceCore.showNotification('✅ Snapshot schedule created successfully', 'success');
        
    } catch (error) {
        console.error('❌ Error scheduling snapshot:', error);
        PersistenceCore.showNotification('❌ Failed to schedule snapshot', 'error');
    }
}

/**
 * Restore from snapshot
 * @param {string} snapshotId - Snapshot ID
 * @param {string} snapshotName - Snapshot name
 * @returns {Promise<void>}
 */
async function restoreSnapshot(snapshotId, snapshotName) {
    console.log(`🔄 Restoring from snapshot: ${snapshotName} (${snapshotId})`);
    
    const confirmed = confirm(`Are you sure you want to restore from snapshot "${snapshotName}"? This will revert the system to the snapshot state.`);
    if (!confirmed) return;
    
    try {
        PersistenceCore.showNotification(`🔄 Restoring from snapshot "${snapshotName}"...`, 'info');
        
        await PersistenceCore.apiPost(`/snapshots/${snapshotId}/restore`);
        PersistenceCore.showNotification(`✅ Restore from "${snapshotName}" completed successfully`, 'success');
        
        // Refresh snapshots after restore
        setTimeout(() => refreshSnapshots(), 2000);
        
    } catch (error) {
        console.error('❌ Error restoring snapshot:', error);
        PersistenceCore.showNotification(`❌ Failed to restore from "${snapshotName}"`, 'error');
    }
}

/**
 * Delete snapshot
 * @param {string} snapshotId - Snapshot ID
 * @param {string} snapshotName - Snapshot name
 * @returns {Promise<void>}
 */
async function deleteSnapshot(snapshotId, snapshotName) {
    console.log(`đŸ—‘ī¸ Deleting snapshot: ${snapshotName} (${snapshotId})`);
    
    const confirmed = confirm(`Are you sure you want to delete snapshot "${snapshotName}"? This action cannot be undone.`);
    if (!confirmed) return;
    
    try {
        await PersistenceCore.apiDelete(`/snapshots/${snapshotId}`);
        PersistenceCore.showNotification(`✅ Snapshot "${snapshotName}" deleted successfully`, 'success');
        await refreshSnapshots();
        
    } catch (error) {
        console.error('❌ Error deleting snapshot:', error);
        PersistenceCore.showNotification(`❌ Failed to delete "${snapshotName}"`, 'error');
    }
}

/**
 * Download snapshot
 * @param {string} snapshotId - Snapshot ID
 * @param {string} snapshotName - Snapshot name
 * @returns {Promise<void>}
 */
async function downloadSnapshot(snapshotId, snapshotName) {
    console.log(`💾 Downloading snapshot: ${snapshotName} (${snapshotId})`);
    
    try {
        PersistenceCore.showNotification(`💾 Preparing download for "${snapshotName}"...`, 'info');
        
        // Create download link
        const downloadUrl = `/api/snapshots/${snapshotId}/download`;
        const link = document.createElement('a');
        link.href = downloadUrl;
        link.download = `${snapshotName}.tar.gz`;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        
        PersistenceCore.showNotification(`✅ Download started for "${snapshotName}"`, 'success');
        
    } catch (error) {
        console.error('❌ Error downloading snapshot:', error);
        PersistenceCore.showNotification(`❌ Failed to download "${snapshotName}"`, 'error');
    }
}

// =============================================================================
// SNAPSHOT MODAL FUNCTIONS
// =============================================================================

/**
 * Show snapshot creation modal
 * @returns {Promise<string|null>}
 */
async function showSnapshotCreationModal() {
    return new Promise((resolve) => {
        const modalHtml = `
            <div id="snapshotCreationModal" class="modal" style="display: block;">
                <div class="modal-content" style="max-width: 500px;">
                    <div class="modal-header">
                        <h3><i class="fas fa-camera"></i> Create Snapshot</h3>
                        <button class="close-btn" onclick="closeSnapshotCreationModal(null)">
                            <i class="fas fa-times"></i>
                        </button>
                    </div>
                    <div class="modal-body">
                        <form id="snapshotCreationForm">
                            <div class="form-group">
                                <label>Snapshot Type:</label>
                                <select id="snapshotType" required>
                                    <option value="system">System Snapshot</option>
                                    <option value="storage">Storage Snapshot</option>
                                    <option value="full">Full System + Storage</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label>Description (Optional):</label>
                                <textarea id="snapshotDescription" placeholder="Enter snapshot description..."></textarea>
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button onclick="closeSnapshotCreationModal(null)" class="btn btn-secondary">Cancel</button>
                        <button onclick="submitSnapshotCreation()" class="btn btn-primary">Create Snapshot</button>
                    </div>
                </div>
            </div>
        `;
        
        // Add modal to DOM
        document.body.insertAdjacentHTML('beforeend', modalHtml);
        document.body.classList.add('modal-open');
        
        // Add modal functions
        window.closeSnapshotCreationModal = (result) => {
            const modal = document.getElementById('snapshotCreationModal');
            if (modal) {
                modal.remove();
                document.body.classList.remove('modal-open');
            }
            delete window.closeSnapshotCreationModal;
            delete window.submitSnapshotCreation;
            resolve(result);
        };
        
        window.submitSnapshotCreation = () => {
            const type = document.getElementById('snapshotType').value;
            const description = document.getElementById('snapshotDescription').value;
            
            window.closeSnapshotCreationModal({ type, description });
        };
    });
}

/**
 * Show snapshot schedule modal
 * @returns {Promise<object|null>}
 */
async function showSnapshotScheduleModal() {
    return new Promise((resolve) => {
        const modalHtml = `
            <div id="snapshotScheduleModal" class="modal" style="display: block;">
                <div class="modal-content" style="max-width: 600px;">
                    <div class="modal-header">
                        <h3><i class="fas fa-clock"></i> Schedule Snapshots</h3>
                        <button class="close-btn" onclick="closeSnapshotScheduleModal(null)">
                            <i class="fas fa-times"></i>
                        </button>
                    </div>
                    <div class="modal-body">
                        <form id="snapshotScheduleForm">
                            <div class="form-group">
                                <label>Schedule Name:</label>
                                <input type="text" id="scheduleName" required placeholder="Enter schedule name">
                            </div>
                            <div class="form-group">
                                <label>Frequency:</label>
                                <select id="scheduleFrequency" required>
                                    <option value="daily">Daily</option>
                                    <option value="weekly">Weekly</option>
                                    <option value="monthly">Monthly</option>
                                </select>
                            </div>
                            <div class="form-group">
                                <label>Time:</label>
                                <input type="time" id="scheduleTime" required value="02:00">
                            </div>
                            <div class="form-group">
                                <label>Retention (days):</label>
                                <input type="number" id="retentionDays" required value="30" min="1" max="365">
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button onclick="closeSnapshotScheduleModal(null)" class="btn btn-secondary">Cancel</button>
                        <button onclick="submitSnapshotSchedule()" class="btn btn-primary">Create Schedule</button>
                    </div>
                </div>
            </div>
        `;
        
        // Add modal to DOM
        document.body.insertAdjacentHTML('beforeend', modalHtml);
        document.body.classList.add('modal-open');
        
        // Add modal functions
        window.closeSnapshotScheduleModal = (result) => {
            const modal = document.getElementById('snapshotScheduleModal');
            if (modal) {
                modal.remove();
                document.body.classList.remove('modal-open');
            }
            delete window.closeSnapshotScheduleModal;
            delete window.submitSnapshotSchedule;
            resolve(result);
        };
        
        window.submitSnapshotSchedule = () => {
            const name = document.getElementById('scheduleName').value;
            const frequency = document.getElementById('scheduleFrequency').value;
            const time = document.getElementById('scheduleTime').value;
            const retention = parseInt(document.getElementById('retentionDays').value);
            
            if (!name || !frequency || !time || !retention) {
                PersistenceCore.showNotification('Please fill in all fields', 'error');
                return;
            }
            
            window.closeSnapshotScheduleModal({ name, frequency, time, retention });
        };
    });
}

// =============================================================================
// SNAPSHOT MONITORING
// =============================================================================

/**
 * Start snapshot monitoring with automatic refresh
 */
function startSnapshotMonitoring() {
    console.log('📸 Starting snapshot monitoring...');
    
    // Clear existing interval
    if (snapshotsState.refreshInterval) {
        clearInterval(snapshotsState.refreshInterval);
    }
    
    // Set up refresh interval
    snapshotsState.refreshInterval = setInterval(async () => {
        if (!snapshotsState.isRefreshing) {
            await refreshSnapshots();
        }
    }, PersistenceCore.config.REFRESH_INTERVALS.SNAPSHOT_DATA);
    
    // Initial refresh
    refreshSnapshots();
}

/**
 * Stop snapshot monitoring
 */
function stopSnapshotMonitoring() {
    console.log('âšī¸ Stopping snapshot monitoring...');
    
    if (snapshotsState.refreshInterval) {
        clearInterval(snapshotsState.refreshInterval);
        snapshotsState.refreshInterval = null;
    }
}

// =============================================================================
// INITIALIZATION
// =============================================================================

/**
 * Initialize snapshots module
 */
function initializeSnapshotsModule() {
    console.log('📸 Initializing snapshots management module...');
    
    // Start monitoring if authenticated
    if (PersistenceAuth.state.isAuthenticated) {
        startSnapshotMonitoring();
    }
    
    // Listen for authentication changes
    window.addEventListener('auth-state-changed', (event) => {
        if (event.detail.isAuthenticated) {
            startSnapshotMonitoring();
        } else {
            stopSnapshotMonitoring();
        }
    });
}

// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', initializeSnapshotsModule);

// =============================================================================
// EXPORT FOR MODULE SYSTEM
// =============================================================================

window.PersistenceSnapshots = {
    state: snapshotsState,
    refreshSnapshots,
    getSnapshotStats,
    createSnapshot,
    scheduleSnapshot,
    restoreSnapshot,
    deleteSnapshot,
    downloadSnapshot,
    showSnapshotCreationModal,
    showSnapshotScheduleModal,
    startSnapshotMonitoring,
    stopSnapshotMonitoring,
    initializeSnapshotsModule
};

console.log('✅ PersistenceOS Snapshots Management Module loaded');
openSUSE Build Service is sponsored by