/**
 * Advanced History Manager
 * Supports undo/redo for ALL operations including image changes
 */

class HistoryManager {
  constructor(maxHistory = 50) {
    this.maxHistory = maxHistory;
    this.stack = [];
    this.currentIndex = -1;
    this.isApplying = false;
    this.listeners = [];
  }

  /**
   * Save a snapshot to history
   */
  saveSnapshot(action, data) {
    if (this.isApplying) return;

    // Remove any states after current index (when user makes new change after undo)
    this.stack = this.stack.slice(0, this.currentIndex + 1);

    // Create snapshot
    const snapshot = {
      id: Date.now() + Math.random(),
      action: action,
      timestamp: new Date().toLocaleTimeString(),
      data: this.cloneData(data)
    };

    // Add to stack
    this.stack.push(snapshot);

    // Limit stack size
    if (this.stack.length > this.maxHistory) {
      this.stack.shift();
    } else {
      this.currentIndex++;
    }

    this.notifyListeners('save', snapshot);
    this.updateUI();
  }

  /**
   * Deep clone data
   */
  cloneData(data) {
    if (!data) return null;

    const cloned = {};

    // Clone image data
    if (data.imageData) {
      cloned.imageData = data.imageData; // Base64 string
    }

    // Clone file info
    if (data.fileInfo) {
      cloned.fileInfo = { ...data.fileInfo };
    }

    // Clone adjustments
    if (data.adjustments) {
      cloned.adjustments = JSON.parse(JSON.stringify(data.adjustments));
    }

    // Clone other states
    if (data.states) {
      cloned.states = JSON.parse(JSON.stringify(data.states));
    }

    // Clone CSS filters
    if (data.cssFilter) {
      cloned.cssFilter = data.cssFilter;
    }

    // Clone zoom
    if (data.zoom !== undefined) {
      cloned.zoom = data.zoom;
    }

    return cloned;
  }

  /**
   * Undo to previous state
   */
  undo() {
    if (!this.canUndo()) {
      console.log('[History] Cannot undo - at beginning');
      return false;
    }

    this.currentIndex--;
    const snapshot = this.stack[this.currentIndex];

    this.isApplying = true;
    this.applySnapshot(snapshot);
    this.isApplying = false;

    this.notifyListeners('undo', snapshot);
    this.updateUI();

    return true;
  }

  /**
   * Redo to next state
   */
  redo() {
    if (!this.canRedo()) {
      console.log('[History] Cannot redo - at end');
      return false;
    }

    this.currentIndex++;
    const snapshot = this.stack[this.currentIndex];

    this.isApplying = true;
    this.applySnapshot(snapshot);
    this.isApplying = false;

    this.notifyListeners('redo', snapshot);
    this.updateUI();

    return true;
  }

  /**
   * Apply a snapshot
   */
  applySnapshot(snapshot) {
    if (!snapshot || !snapshot.data) return;

    const data = snapshot.data;

    // Restore image
    if (data.imageData && window.previewImage) {
      window.previewImage.src = data.imageData;
    }

    // Restore file info
    if (data.fileInfo && window.selectedFile) {
      // Update file info display
      if (document.getElementById('fileName')) {
        document.getElementById('fileName').textContent = data.fileInfo.name || '-';
      }
      if (document.getElementById('fileSize')) {
        document.getElementById('fileSize').textContent = data.fileInfo.size || '-';
      }
      if (document.getElementById('fileType')) {
        document.getElementById('fileType').textContent = data.fileInfo.type || '-';
      }
      if (document.getElementById('imageDimensions')) {
        document.getElementById('imageDimensions').textContent = data.fileInfo.dimensions || '-';
      }
    }

    // Restore adjustments
    if (data.adjustments && window.adjustments) {
      Object.assign(window.adjustments, data.adjustments);
      this.updateAllControls(data.adjustments);
    }

    // Restore states
    if (data.states) {
      if (data.states.bwEnabled !== undefined && window.bwEnabled !== undefined) {
        window.bwEnabled = data.states.bwEnabled;
        const bwToggle = document.getElementById('bwToggle');
        if (bwToggle) bwToggle.checked = data.states.bwEnabled;
      }

      if (data.states.curvePoints && window.curvePoints) {
        window.curvePoints = JSON.parse(JSON.stringify(data.states.curvePoints));
        if (typeof drawCurve === 'function') drawCurve();
      }

      if (data.states.levelsValues && window.levelsValues) {
        Object.assign(window.levelsValues, data.states.levelsValues);
        if (typeof drawLevelsHistogram === 'function') drawLevelsHistogram();
      }
    }

    // Restore CSS filter
    if (data.cssFilter !== undefined && window.previewImage) {
      window.previewImage.style.filter = data.cssFilter;
    }

    // Restore zoom
    if (data.zoom !== undefined && window.currentZoom !== undefined) {
      window.currentZoom = data.zoom;
      if (typeof updateZoom === 'function') updateZoom();
    }

    // Recalculate histogram
    setTimeout(() => {
      if (typeof calculateHistogram === 'function') {
        calculateHistogram();
      }
    }, 100);
  }

  /**
   * Update all UI controls
   */
  updateAllControls(adjustments) {
    Object.keys(adjustments).forEach(key => {
      const slider = document.getElementById(key + 'Slider');
      const input = document.getElementById(key + 'Input');
      const value = document.getElementById(key + 'Value');

      if (slider) slider.value = adjustments[key];
      if (input) input.value = adjustments[key];
      if (value) {
        // Format value display
        if (key === 'hue') {
          value.textContent = adjustments[key] + '°';
        } else if (key.includes('gamma') || key.includes('midtones')) {
          value.textContent = parseFloat(adjustments[key]).toFixed(2);
        } else if (key === 'exposure') {
          value.textContent = parseFloat(adjustments[key]).toFixed(1);
        } else {
          value.textContent = adjustments[key];
        }
      }
    });

    // Update special controls
    if (typeof updateColorPreview === 'function') updateColorPreview();
    if (typeof updateComparisonBars === 'function') updateComparisonBars();
  }

  /**
   * Can undo?
   */
  canUndo() {
    return this.currentIndex > 0;
  }

  /**
   * Can redo?
   */
  canRedo() {
    return this.currentIndex < this.stack.length - 1;
  }

  /**
   * Get current snapshot
   */
  getCurrentSnapshot() {
    return this.stack[this.currentIndex];
  }

  /**
   * Get all snapshots
   */
  getAllSnapshots() {
    return this.stack;
  }

  /**
   * Clear history
   */
  clear() {
    this.stack = [];
    this.currentIndex = -1;
    this.notifyListeners('clear');
    this.updateUI();
  }

  /**
   * Jump to specific snapshot
   */
  jumpTo(index) {
    if (index < 0 || index >= this.stack.length) return false;

    this.currentIndex = index;
    const snapshot = this.stack[index];

    this.isApplying = true;
    this.applySnapshot(snapshot);
    this.isApplying = false;

    this.notifyListeners('jump', snapshot);
    this.updateUI();

    return true;
  }

  /**
   * Add listener
   */
  addListener(callback) {
    this.listeners.push(callback);
  }

  /**
   * Notify listeners
   */
  notifyListeners(event, data) {
    this.listeners.forEach(callback => {
      try {
        callback(event, data);
      } catch (error) {
        console.error('[History] Listener error:', error);
      }
    });
  }

  /**
   * Update UI buttons
   */
  updateUI() {
    const undoBtn = document.getElementById('undoBtn');
    const redoBtn = document.getElementById('redoBtn');

    if (undoBtn) {
      undoBtn.disabled = !this.canUndo();
      undoBtn.title = this.canUndo() 
        ? `Undo: ${this.stack[this.currentIndex - 1]?.action}` 
        : 'Nothing to undo';
    }

    if (redoBtn) {
      redoBtn.disabled = !this.canRedo();
      redoBtn.title = this.canRedo() 
        ? `Redo: ${this.stack[this.currentIndex + 1]?.action}` 
        : 'Nothing to redo';
    }

    // Update history panel
    this.updateHistoryPanel();
  }

  /**
   * Update history panel
   */
  updateHistoryPanel() {
    const historyContent = document.getElementById('historyContent');
    if (!historyContent) return;

    if (this.stack.length === 0) {
      historyContent.innerHTML = '<div class="history-empty">No history yet</div>';
      return;
    }

    let html = '';
    this.stack.forEach((snapshot, index) => {
      const isActive = index === this.currentIndex;
      const isFuture = index > this.currentIndex;
      
      html += `
        <div class="history-item ${isActive ? 'active' : ''} ${isFuture ? 'future' : ''}" 
             data-index="${index}"
             onclick="historyManager.jumpTo(${index})">
          <div class="history-action">${snapshot.action}</div>
          <div class="history-time">${snapshot.timestamp}</div>
          ${isActive ? '<div class="history-current">← Current</div>' : ''}
        </div>
      `;
    });

    historyContent.innerHTML = html;

    // Scroll to active item
    setTimeout(() => {
      const activeItem = historyContent.querySelector('.history-item.active');
      if (activeItem) {
        activeItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
      }
    }, 100);
  }

  /**
   * Get history stats
   */
  getStats() {
    return {
      total: this.stack.length,
      current: this.currentIndex + 1,
      canUndo: this.canUndo(),
      canRedo: this.canRedo(),
      memoryUsage: this.estimateMemoryUsage()
    };
  }

  /**
   * Estimate memory usage
   */
  estimateMemoryUsage() {
    let size = 0;
    this.stack.forEach(snapshot => {
      if (snapshot.data.imageData) {
        size += snapshot.data.imageData.length;
      }
      size += JSON.stringify(snapshot.data).length;
    });
    return Math.round(size / 1024 / 1024 * 100) / 100; // MB
  }

  /**
   * Export history
   */
  exportHistory() {
    return {
      version: '1.0',
      exported: new Date().toISOString(),
      stack: this.stack,
      currentIndex: this.currentIndex
    };
  }

  /**
   * Import history
   */
  importHistory(data) {
    if (!data || !data.stack) return false;

    this.stack = data.stack;
    this.currentIndex = data.currentIndex;
    this.updateUI();

    return true;
  }
}

// Create global instance
window.historyManager = new HistoryManager(50);

// Add keyboard shortcuts
document.addEventListener('keydown', (e) => {
  // Ctrl+Z for Undo
  if (e.ctrlKey && e.key === 'z' && !e.shiftKey) {
    e.preventDefault();
    window.historyManager.undo();
  }
  // Ctrl+Y or Ctrl+Shift+Z for Redo
  else if ((e.ctrlKey && e.key === 'y') || (e.ctrlKey && e.shiftKey && e.key === 'z')) {
    e.preventDefault();
    window.historyManager.redo();
  }
});

// Helper function to capture current state
function captureCurrentState() {
  const state = {
    imageData: window.previewImage?.src || null,
    fileInfo: {
      name: document.getElementById('fileName')?.textContent || null,
      size: document.getElementById('fileSize')?.textContent || null,
      type: document.getElementById('fileType')?.textContent || null,
      dimensions: document.getElementById('imageDimensions')?.textContent || null
    },
    adjustments: window.adjustments ? JSON.parse(JSON.stringify(window.adjustments)) : null,
    states: {
      bwEnabled: window.bwEnabled,
      curvePoints: window.curvePoints ? JSON.parse(JSON.stringify(window.curvePoints)) : null,
      levelsValues: window.levelsValues ? JSON.parse(JSON.stringify(window.levelsValues)) : null
    },
    cssFilter: window.previewImage?.style.filter || '',
    zoom: window.currentZoom || 1
  };

  return state;
}

// Export helper
window.captureCurrentState = captureCurrentState;

console.log('[History] History Manager initialized ✓');
console.log('[History] Max history:', window.historyManager.maxHistory);
console.log('[History] Keyboard shortcuts: Ctrl+Z (Undo), Ctrl+Y (Redo)');
