/* IndexedDB wrapper for offline data storage in SFM */
/* Handles unit data, status snapshots, and pending edit queue */

class OfflineDB {
  constructor() {
    this.dbName = 'sfm-offline-db';
    this.version = 1;
    this.db = null;
  }

  // Initialize database
  async init() {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.version);

      request.onerror = () => {
        console.error('IndexedDB error:', request.error);
        reject(request.error);
      };

      request.onsuccess = () => {
        this.db = request.result;
        console.log('IndexedDB initialized successfully');
        resolve(this.db);
      };

      request.onupgradeneeded = (event) => {
        const db = event.target.result;

        // Units store - full unit details
        if (!db.objectStoreNames.contains('units')) {
          const unitsStore = db.createObjectStore('units', { keyPath: 'id' });
          unitsStore.createIndex('device_type', 'device_type', { unique: false });
          unitsStore.createIndex('deployed', 'deployed', { unique: false });
          console.log('Created units object store');
        }

        // Status snapshot store - latest status data
        if (!db.objectStoreNames.contains('status-snapshot')) {
          db.createObjectStore('status-snapshot', { keyPath: 'timestamp' });
          console.log('Created status-snapshot object store');
        }

        // Pending edits store - offline edit queue
        if (!db.objectStoreNames.contains('pending-edits')) {
          const editsStore = db.createObjectStore('pending-edits', {
            keyPath: 'id',
            autoIncrement: true
          });
          editsStore.createIndex('unitId', 'unitId', { unique: false });
          editsStore.createIndex('timestamp', 'timestamp', { unique: false });
          console.log('Created pending-edits object store');
        }
      };
    });
  }

  // ===== UNITS OPERATIONS =====

  // Save or update a unit
  async saveUnit(unit) {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['units'], 'readwrite');
      const store = transaction.objectStore('units');
      const request = store.put(unit);

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  // Get a single unit by ID
  async getUnit(unitId) {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['units'], 'readonly');
      const store = transaction.objectStore('units');
      const request = store.get(unitId);

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  // Get all units
  async getAllUnits() {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['units'], 'readonly');
      const store = transaction.objectStore('units');
      const request = store.getAll();

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  // Delete a unit
  async deleteUnit(unitId) {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['units'], 'readwrite');
      const store = transaction.objectStore('units');
      const request = store.delete(unitId);

      request.onsuccess = () => resolve();
      request.onerror = () => reject(request.error);
    });
  }

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

  // Save status snapshot
  async saveSnapshot(snapshot) {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['status-snapshot'], 'readwrite');
      const store = transaction.objectStore('status-snapshot');

      // Add timestamp
      const snapshotWithTimestamp = {
        ...snapshot,
        timestamp: Date.now()
      };

      const request = store.put(snapshotWithTimestamp);

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  // Get latest status snapshot
  async getLatestSnapshot() {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['status-snapshot'], 'readonly');
      const store = transaction.objectStore('status-snapshot');
      const request = store.getAll();

      request.onsuccess = () => {
        const snapshots = request.result;
        if (snapshots.length > 0) {
          // Return the most recent snapshot
          const latest = snapshots.reduce((prev, current) =>
            (prev.timestamp > current.timestamp) ? prev : current
          );
          resolve(latest);
        } else {
          resolve(null);
        }
      };
      request.onerror = () => reject(request.error);
    });
  }

  // Clear old snapshots (keep only latest)
  async clearOldSnapshots() {
    if (!this.db) await this.init();

    return new Promise(async (resolve, reject) => {
      const transaction = this.db.transaction(['status-snapshot'], 'readwrite');
      const store = transaction.objectStore('status-snapshot');
      const getAllRequest = store.getAll();

      getAllRequest.onsuccess = () => {
        const snapshots = getAllRequest.result;

        if (snapshots.length > 1) {
          // Sort by timestamp, keep only the latest
          snapshots.sort((a, b) => b.timestamp - a.timestamp);

          // Delete all except the first (latest)
          for (let i = 1; i < snapshots.length; i++) {
            store.delete(snapshots[i].timestamp);
          }
        }

        resolve();
      };

      getAllRequest.onerror = () => reject(getAllRequest.error);
    });
  }

  // ===== PENDING EDITS OPERATIONS =====

  // Queue an edit for offline sync
  async queueEdit(unitId, changes) {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['pending-edits'], 'readwrite');
      const store = transaction.objectStore('pending-edits');

      const edit = {
        unitId,
        changes,
        timestamp: Date.now()
      };

      const request = store.add(edit);

      request.onsuccess = () => {
        console.log(`Queued edit for unit ${unitId}`);
        resolve(request.result);
      };
      request.onerror = () => reject(request.error);
    });
  }

  // Get all pending edits
  async getPendingEdits() {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['pending-edits'], 'readonly');
      const store = transaction.objectStore('pending-edits');
      const request = store.getAll();

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  // Get pending edits count
  async getPendingEditsCount() {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['pending-edits'], 'readonly');
      const store = transaction.objectStore('pending-edits');
      const request = store.count();

      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });
  }

  // Clear a synced edit
  async clearEdit(editId) {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['pending-edits'], 'readwrite');
      const store = transaction.objectStore('pending-edits');
      const request = store.delete(editId);

      request.onsuccess = () => {
        console.log(`Cleared edit ${editId} from queue`);
        resolve();
      };
      request.onerror = () => reject(request.error);
    });
  }

  // Clear all pending edits
  async clearAllEdits() {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['pending-edits'], 'readwrite');
      const store = transaction.objectStore('pending-edits');
      const request = store.clear();

      request.onsuccess = () => {
        console.log('Cleared all pending edits');
        resolve();
      };
      request.onerror = () => reject(request.error);
    });
  }

  // ===== UTILITY OPERATIONS =====

  // Clear all data (for debugging/reset)
  async clearAllData() {
    if (!this.db) await this.init();

    return new Promise((resolve, reject) => {
      const storeNames = ['units', 'status-snapshot', 'pending-edits'];
      const transaction = this.db.transaction(storeNames, 'readwrite');

      storeNames.forEach(storeName => {
        transaction.objectStore(storeName).clear();
      });

      transaction.oncomplete = () => {
        console.log('Cleared all offline data');
        resolve();
      };
      transaction.onerror = () => reject(transaction.error);
    });
  }

  // Get database statistics
  async getStats() {
    if (!this.db) await this.init();

    const unitsCount = await new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['units'], 'readonly');
      const request = transaction.objectStore('units').count();
      request.onsuccess = () => resolve(request.result);
      request.onerror = () => reject(request.error);
    });

    const pendingEditsCount = await this.getPendingEditsCount();

    const hasSnapshot = await new Promise((resolve, reject) => {
      const transaction = this.db.transaction(['status-snapshot'], 'readonly');
      const request = transaction.objectStore('status-snapshot').count();
      request.onsuccess = () => resolve(request.result > 0);
      request.onerror = () => reject(request.error);
    });

    return {
      unitsCount,
      pendingEditsCount,
      hasSnapshot
    };
  }
}

// Create global instance
window.offlineDB = new OfflineDB();

// Initialize on page load
document.addEventListener('DOMContentLoaded', async () => {
  try {
    await window.offlineDB.init();
    console.log('Offline database ready');

    // Display pending edits count if any
    const pendingCount = await window.offlineDB.getPendingEditsCount();
    if (pendingCount > 0) {
      console.log(`${pendingCount} pending edits in queue`);
      // Could show a badge in the UI here
    }
  } catch (error) {
    console.error('Failed to initialize offline database:', error);
  }
});
