export const diffHistory = (a: any, b: any) => ({ added: [], removed: [], changed: [] });

export interface HistoryEntry<T> {
  state: T;
  timestamp: number;
}

export interface HistoryStatistics {
  totalSteps: number;
  snapshotCount: number;
  patchCount: number;
  currentIndex: number;
  canUndo: boolean;
  canRedo: boolean;
  memoryUsageBytes: number;
}

export class IncrementalHistory<T> {
  private history: HistoryEntry<T>[] = [];
  private currentIndex = -1;
  private maxHistory: number;
  private snapshotInterval: number;

  constructor(initialState: T, options?: { maxHistory?: number; snapshotInterval?: number }) {
    this.maxHistory = options?.maxHistory ?? 50;
    this.snapshotInterval = options?.snapshotInterval ?? 10;
    this.saveState(initialState);
  }

  saveState(state: T): boolean {
    // Remove any future history if we're not at the end
    if (this.currentIndex < this.history.length - 1) {
      this.history = this.history.slice(0, this.currentIndex + 1);
    }

    this.history.push({
      state,
      timestamp: Date.now()
    });

    this.currentIndex++;

    // Limit history size
    if (this.history.length > this.maxHistory) {
      this.history.shift();
      this.currentIndex--;
    }

    return true;
  }

  undo(): T | null {
    if (this.currentIndex > 0) {
      this.currentIndex--;
      return this.history[this.currentIndex].state;
    }
    return null;
  }

  redo(): T | null {
    if (this.currentIndex < this.history.length - 1) {
      this.currentIndex++;
      return this.history[this.currentIndex].state;
    }
    return null;
  }

  canUndo(): boolean {
    return this.currentIndex > 0;
  }

  canRedo(): boolean {
    return this.currentIndex < this.history.length - 1;
  }

  getStatistics(): HistoryStatistics {
    const memoryUsageBytes = JSON.stringify(this.history).length * 2; // Rough estimate

    return {
      totalSteps: this.history.length,
      snapshotCount: Math.ceil(this.history.length / this.snapshotInterval),
      patchCount: this.history.length - Math.ceil(this.history.length / this.snapshotInterval),
      currentIndex: this.currentIndex,
      canUndo: this.canUndo(),
      canRedo: this.canRedo(),
      memoryUsageBytes
    };
  }

  push(entry: HistoryEntry<T>) {
    this.history.push(entry);
  }

  getHistory() {
    return this.history;
  }

  clear() {
    this.history = [];
    this.currentIndex = -1;
  }
}
