// Undo / redo action creators. Captures snapshots of timeline-shaped state
// each time `pushHistory` is called, then exposes undo/redo that restore
// from the snapshot stack.

import type { TimelineSnapshot } from '@/types';
import type { EditorActions, Getter, Setter } from './types';

const HISTORY_CAP = 50;

function clone<T>(v: T): T {
  return JSON.parse(JSON.stringify(v));
}

export function createHistoryActions(
  set: Setter,
  get: Getter,
): Pick<EditorActions, 'pushHistory' | 'undo' | 'redo' | 'canUndo' | 'canRedo'> {
  return {
    pushHistory: (_label: string) => {
      const snap: TimelineSnapshot = {
        tracks: clone(get().tracks),
        clips: clone(get().clips),
        assets: [],
        silenceSegments: clone(get().silenceSegments),
        subtitles: clone(get().subtitles),
        selection: clone(get().selection),
      };
      set((s) => {
        const truncated = s.history.slice(0, s.historyIndex + 1);
        truncated.push(snap);
        const cap = truncated.slice(-HISTORY_CAP);
        return { history: cap, historyIndex: cap.length - 1 };
      });
    },

    undo: () => {
      const { historyIndex, history } = get();
      if (historyIndex <= 0) return;
      const prev = history[historyIndex - 1];
      set({
        tracks: clone(prev.tracks),
        clips: clone(prev.clips),
        silenceSegments: clone(prev.silenceSegments),
        subtitles: clone(prev.subtitles),
        selection: clone(prev.selection),
        historyIndex: historyIndex - 1,
      });
    },

    redo: () => {
      const { historyIndex, history } = get();
      if (historyIndex >= history.length - 1) return;
      const next = history[historyIndex + 1];
      set({
        tracks: clone(next.tracks),
        clips: clone(next.clips),
        silenceSegments: clone(next.silenceSegments),
        subtitles: clone(next.subtitles),
        selection: clone(next.selection),
        historyIndex: historyIndex + 1,
      });
    },

    canUndo: () => get().historyIndex > 0,
    canRedo: () => get().historyIndex < get().history.length - 1,
  };
}