/**
 * Save System Manager
 * Handles game saves, versioning, compression, and export/import
 */

import LZString from 'lz-string';

export class SaveManager {
  static VERSION = 1;
  static SAVE_SLOTS = 3;

  gameStore: any;
  uiStore: any;
  settingsStore: any;
  autoSaveInterval: any;

  constructor(gameStore: any, uiStore: any, settingsStore: any) {
    this.gameStore = gameStore;
    this.uiStore = uiStore;
    this.settingsStore = settingsStore;
    this.autoSaveInterval = null;
  }

  /**
   * Create a save state object
   * @returns {Object} - Complete save state
   */
  createSaveState() {
    return {
      version: SaveManager.VERSION,
      timestamp: Date.now(),
      game: this.gameStore.getState(),
      settings: this.settingsStore.getState()
    };
  }

  /**
   * Compress save data
   * @param {Object} data - Data to compress
   * @returns {string} - Compressed string
   */
  compress(data) {
    const jsonString = JSON.stringify(data);
    return LZString.compressToUTF16(jsonString);
  }

  /**
   * Decompress save data
   * @param {string} compressed - Compressed string
   * @returns {Object|null} - Decompressed data or null on error
   */
  decompress(compressed) {
    try {
      const jsonString = LZString.decompressFromUTF16(compressed);
      return JSON.parse(jsonString);
    } catch (error) {
      console.error('Failed to decompress save data:', error);
      return null;
    }
  }

  /**
   * Save to a slot
   * @param {number} slotIndex - Slot index (0-2)
   * @returns {boolean} - Success
   */
  saveToSlot(slotIndex) {
    if (slotIndex < 0 || slotIndex >= SaveManager.SAVE_SLOTS) {
      console.error('Invalid save slot:', slotIndex);
      return false;
    }

    try {
      const saveState = this.createSaveState();
      const compressed = this.compress(saveState);
      
      localStorage.setItem(`suno-rpg-slot-${slotIndex}`, compressed);
      localStorage.setItem(`suno-rpg-slot-${slotIndex}-meta`, JSON.stringify({
        timestamp: saveState.timestamp,
        playerName: saveState.game.player.name,
        playerLevel: saveState.game.player.level,
        playTime: saveState.game.player.statistics.totalPlayTime
      }));

      return true;
    } catch (error) {
      console.error('Failed to save:', error);
      return false;
    }
  }

  /**
   * Load from a slot
   * @param {number} slotIndex - Slot index (0-2)
   * @returns {boolean} - Success
   */
  loadFromSlot(slotIndex) {
    if (slotIndex < 0 || slotIndex >= SaveManager.SAVE_SLOTS) {
      console.error('Invalid save slot:', slotIndex);
      return false;
    }

    try {
      const compressed = localStorage.getItem(`suno-rpg-slot-${slotIndex}`);
      
      if (!compressed) {
        console.error('No save data in slot:', slotIndex);
        return false;
      }

      const saveState = this.decompress(compressed);
      
      if (!saveState) {
        console.error('Failed to decompress save data');
        return false;
      }

      // Validate version
      if (saveState.version !== SaveManager.VERSION) {
        console.warn('Save version mismatch, attempting migration...');
        // Migration logic would go here
      }

      // Restore state
      // Note: Zustand's persist middleware handles this, but we can manually set state here
      // For now, we'll rely on the persist middleware
      
      return true;
    } catch (error) {
      console.error('Failed to load save:', error);
      return false;
    }
  }

  /**
   * Get save slot metadata
   * @param {number} slotIndex - Slot index
   * @returns {Object|null} - Metadata or null if empty
   */
  getSlotMetadata(slotIndex) {
    try {
      const meta = localStorage.getItem(`suno-rpg-slot-${slotIndex}-meta`);
      return meta ? JSON.parse(meta) : null;
    } catch (error) {
      return null;
    }
  }

  /**
   * Check if slot has save data
   * @param {number} slotIndex - Slot index
   * @returns {boolean} - Has data
   */
  slotHasData(slotIndex) {
    return localStorage.getItem(`suno-rpg-slot-${slotIndex}`) !== null;
  }

  /**
   * Delete save slot
   * @param {number} slotIndex - Slot index
   */
  deleteSlot(slotIndex) {
    localStorage.removeItem(`suno-rpg-slot-${slotIndex}`);
    localStorage.removeItem(`suno-rpg-slot-${slotIndex}-meta`);
  }

  /**
   * Export save to file
   * @param {number} slotIndex - Slot index to export
   */
  exportSave(slotIndex) {
    const saveState = this.createSaveState();
    const json = JSON.stringify(saveState, null, 2);
    const blob = new Blob([json], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    
    const link = document.createElement('a');
    link.href = url;
    link.download = `suno-rpg-save-${slotIndex}-${Date.now()}.json`;
    link.click();
    
    URL.revokeObjectURL(url);
  }

  /**
   * Import save from file
   * @param {File} file - Save file
   * @param {number} slotIndex - Target slot index
   * @returns {Promise<boolean>} - Success
   */
  async importSave(file, slotIndex) {
    try {
      const text = await file.text();
      const saveState = JSON.parse(text);
      
      // Validate save state
      if (!saveState.version || !saveState.game || !saveState.settings) {
        throw new Error('Invalid save file format');
      }

      // Save to slot
      const compressed = this.compress(saveState);
      localStorage.setItem(`suno-rpg-slot-${slotIndex}`, compressed);
      localStorage.setItem(`suno-rpg-slot-${slotIndex}-meta`, JSON.stringify({
        timestamp: saveState.timestamp,
        playerName: saveState.game.player.name,
        playerLevel: saveState.game.player.level,
        playTime: saveState.game.player.statistics.totalPlayTime
      }));

      return true;
    } catch (error) {
      console.error('Failed to import save:', error);
      return false;
    }
  }

  /**
   * Start auto-save
   * @param {number} intervalSeconds - Auto-save interval in seconds
   */
  startAutoSave(intervalSeconds = 30) {
    this.stopAutoSave();
    
    this.autoSaveInterval = setInterval(() => {
      const { autoSave } = this.settingsStore.getState().game;
      if (autoSave) {
        this.saveToSlot(0); // Auto-save to slot 0
      }
    }, intervalSeconds * 1000);
  }

  /**
   * Stop auto-save
   */
  stopAutoSave() {
    if (this.autoSaveInterval) {
      clearInterval(this.autoSaveInterval);
      this.autoSaveInterval = null;
    }
  }

  /**
   * Clean up (call on unmount)
   */
  cleanup() {
    this.stopAutoSave();
  }
}

