/**
 * Auto Save Manager
 * 
 * Manages automatic saving of editor content to localStorage
 * Extracted from Holy Habit auto-save functionality
 */

import { AutoSaveData, AutoSaveOptions } from '../types/Editor';

export class AutoSaveManager {
  private editorId: string;
  private storageKey: string;
  private saveInterval: number;
  private maxSize: number;
  private intervalId: NodeJS.Timeout | null = null;
  private lastSaveTime = 0;
  private version = '1.0.0';
  
  // Callbacks
  private onSave?: (data: AutoSaveData) => void;
  private onRestore?: (data: AutoSaveData) => void;
  private onError?: (error: Error) => void;
  
  // Storage availability flag
  private storageAvailable = false;

  constructor(editorId: string, options?: AutoSaveOptions) {
    this.editorId = editorId;
    this.storageKey = options?.key || `holy-editor-autosave-${editorId}`;
    this.saveInterval = options?.interval || 30000; // 30 seconds default
    this.maxSize = options?.maxSize || 1048576; // 1MB default
    
    // Set callbacks
    this.onSave = options?.onSave;
    this.onRestore = options?.onRestore;
    this.onError = options?.onError;
    
    // Check localStorage availability
    this.checkStorageAvailability();
    
    console.log('💾 AutoSaveManager initialized for editor:', editorId);
  }

  /**
   * Check if localStorage is available
   */
  private checkStorageAvailability(): boolean {
    try {
      const testKey = '__holy_editor_test__';
      localStorage.setItem(testKey, 'test');
      localStorage.removeItem(testKey);
      this.storageAvailable = true;
      return true;
    } catch (error) {
      console.warn('⚠️ localStorage not available:', error);
      this.storageAvailable = false;
      this.handleError(new Error('localStorage not available'));
      return false;
    }
  }

  /**
   * Start auto-saving
   */
  public start(getContent: () => string): void {
    if (!this.storageAvailable) {
      console.warn('⚠️ Cannot start auto-save: localStorage not available');
      return;
    }
    
    // Clear any existing interval
    this.stop();
    
    // Save immediately
    this.save(getContent());
    
    // Set up interval
    this.intervalId = setInterval(() => {
      this.save(getContent());
    }, this.saveInterval);
    
    console.log('▶️ Auto-save started with interval:', this.saveInterval);
  }

  /**
   * Stop auto-saving
   */
  public stop(): void {
    if (this.intervalId) {
      clearInterval(this.intervalId);
      this.intervalId = null;
      console.log('⏹️ Auto-save stopped');
    }
  }

  /**
   * Save content to localStorage
   */
  public save(content: string): boolean {
    if (!this.storageAvailable) return false;
    
    try {
      // Check content size
      const contentSize = new Blob([content]).size;
      if (contentSize > this.maxSize) {
        throw new Error(`Content size (${contentSize} bytes) exceeds maximum (${this.maxSize} bytes)`);
      }
      
      // Create save data
      const saveData: AutoSaveData = {
        content,
        timestamp: Date.now(),
        version: this.version,
        editorId: this.editorId
      };
      
      // Save to localStorage
      localStorage.setItem(this.storageKey, JSON.stringify(saveData));
      this.lastSaveTime = saveData.timestamp;
      
      // Call onSave callback
      if (this.onSave) {
        this.onSave(saveData);
      }
      
      console.log('💾 Content auto-saved:', {
        size: contentSize,
        timestamp: new Date(saveData.timestamp).toISOString()
      });
      
      return true;
    } catch (error) {
      console.error('❌ Auto-save failed:', error);
      this.handleError(error as Error);
      return false;
    }
  }

  /**
   * Restore content from localStorage
   */
  public restore(): string | null {
    if (!this.storageAvailable) return null;
    
    try {
      const savedData = localStorage.getItem(this.storageKey);
      if (!savedData) {
        console.log('💾 No saved content found');
        return null;
      }
      
      const data: AutoSaveData = JSON.parse(savedData);
      
      // Validate data structure
      if (!data.content || !data.timestamp || !data.version) {
        throw new Error('Invalid save data structure');
      }
      
      // Check if saved data is from same editor
      if (data.editorId !== this.editorId) {
        console.warn('⚠️ Saved data is from different editor:', data.editorId);
      }
      
      // Call onRestore callback
      if (this.onRestore) {
        this.onRestore(data);
      }
      
      const age = Date.now() - data.timestamp;
      const ageMinutes = Math.floor(age / 60000);
      
      console.log('✅ Content restored:', {
        age: `${ageMinutes} minutes`,
        timestamp: new Date(data.timestamp).toISOString(),
        size: new Blob([data.content]).size
      });
      
      return data.content;
    } catch (error) {
      console.error('❌ Failed to restore content:', error);
      this.handleError(error as Error);
      return null;
    }
  }

  /**
   * Clear saved content
   */
  public clear(): boolean {
    if (!this.storageAvailable) return false;
    
    try {
      localStorage.removeItem(this.storageKey);
      console.log('🗑️ Auto-saved content cleared');
      return true;
    } catch (error) {
      console.error('❌ Failed to clear saved content:', error);
      this.handleError(error as Error);
      return false;
    }
  }

  /**
   * Get save info without restoring content
   */
  public getSaveInfo(): { timestamp: number; size: number } | null {
    if (!this.storageAvailable) return null;
    
    try {
      const savedData = localStorage.getItem(this.storageKey);
      if (!savedData) return null;
      
      const data: AutoSaveData = JSON.parse(savedData);
      const size = new Blob([data.content]).size;
      
      return {
        timestamp: data.timestamp,
        size
      };
    } catch (error) {
      console.error('❌ Failed to get save info:', error);
      return null;
    }
  }

  /**
   * Check if there's saved content
   */
  public hasSavedContent(): boolean {
    return this.getSaveInfo() !== null;
  }

  /**
   * Get time since last save
   */
  public getTimeSinceLastSave(): number {
    if (this.lastSaveTime === 0) return -1;
    return Date.now() - this.lastSaveTime;
  }

  /**
   * Update save interval
   */
  public updateInterval(newInterval: number, getContent?: () => string): void {
    this.saveInterval = newInterval;
    
    // Restart if currently running
    if (this.intervalId && getContent) {
      this.start(getContent);
    }
  }

  /**
   * Handle errors
   */
  private handleError(error: Error): void {
    if (this.onError) {
      this.onError(error);
    }
  }

  /**
   * Get storage key
   */
  public getStorageKey(): string {
    return this.storageKey;
  }

  /**
   * Check if auto-save is running
   */
  public isRunning(): boolean {
    return this.intervalId !== null;
  }

  /**
   * Get all saved editor keys
   */
  public static getAllSavedEditors(): string[] {
    const keys: string[] = [];
    const prefix = 'holy-editor-autosave-';
    
    try {
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key && key.startsWith(prefix)) {
          keys.push(key.substring(prefix.length));
        }
      }
    } catch (error) {
      console.error('❌ Failed to get saved editors:', error);
    }
    
    return keys;
  }

  /**
   * Clear all saved content for all editors
   */
  public static clearAll(): number {
    let cleared = 0;
    const prefix = 'holy-editor-autosave-';
    
    try {
      const keysToRemove: string[] = [];
      
      for (let i = 0; i < localStorage.length; i++) {
        const key = localStorage.key(i);
        if (key && key.startsWith(prefix)) {
          keysToRemove.push(key);
        }
      }
      
      keysToRemove.forEach(key => {
        localStorage.removeItem(key);
        cleared++;
      });
      
      console.log(`🗑️ Cleared ${cleared} auto-saved editors`);
    } catch (error) {
      console.error('❌ Failed to clear all saved content:', error);
    }
    
    return cleared;
  }
}