"use client";
import * as React from "react";
const DEFAULT_STATE = { stack: [], undone: [] };
const STORAGE_KEY = "om:last-operations:v1";
const STACK_LIMIT = 20;
const LAST_OPERATION_TTL_MS = 6e4;
const STACK_RETENTION_MS = 10 * 6e4;
let internalState = DEFAULT_STATE;
if (typeof window !== "undefined") {
  internalState = loadState();
}
const emitter = new EventTarget();
function now() {
  return typeof performance !== "undefined" && performance.now ? Math.round(performance.timeOrigin + performance.now()) : Date.now();
}
function loadState() {
  try {
    const raw = window.localStorage.getItem(STORAGE_KEY);
    if (!raw) return DEFAULT_STATE;
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== "object") return DEFAULT_STATE;
    const stack = Array.isArray(parsed.stack) ? parsed.stack.filter(isValidEntry).map(hydrateEntry) : [];
    const undone = Array.isArray(parsed.undone) ? parsed.undone.filter(isValidEntry).map((raw2) => {
      const hydrated = hydrateEntry(raw2);
      const candidate = raw2;
      const undoneAt = typeof candidate.undoneAt === "number" ? candidate.undoneAt : now();
      return { ...hydrated, undoneAt };
    }) : [];
    return pruneState({ stack, undone });
  } catch {
    return DEFAULT_STATE;
  }
}
function isValidEntry(entry) {
  if (entry == null || typeof entry !== "object") return false;
  const candidate = entry;
  return typeof candidate.id === "string" && typeof candidate.undoToken === "string" && typeof candidate.commandId === "string" && typeof candidate.receivedAt === "number" && typeof candidate.executedAt === "string";
}
function hydrateEntry(entry) {
  const source = entry;
  return {
    id: String(source.id),
    undoToken: String(source.undoToken),
    commandId: String(source.commandId),
    actionLabel: typeof source.actionLabel === "string" ? source.actionLabel : null,
    resourceKind: typeof source.resourceKind === "string" ? source.resourceKind : null,
    resourceId: typeof source.resourceId === "string" ? source.resourceId : null,
    executedAt: typeof source.executedAt === "string" ? source.executedAt : new Date(source.receivedAt || now()).toISOString(),
    receivedAt: typeof source.receivedAt === "number" ? source.receivedAt : now()
  };
}
function persist(state) {
  if (typeof window === "undefined") return;
  try {
    window.localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
  } catch {
  }
}
function pruneState(state) {
  const timestamp = now();
  const stack = state.stack.filter((entry, index, arr) => {
    const duplicateIndex = arr.findIndex((candidate) => candidate.id === entry.id || candidate.undoToken === entry.undoToken);
    if (duplicateIndex !== index) return false;
    return timestamp - entry.receivedAt <= STACK_RETENTION_MS;
  }).sort((a, b) => a.receivedAt - b.receivedAt).slice(-STACK_LIMIT);
  const undone = state.undone.filter((entry) => timestamp - entry.undoneAt <= STACK_RETENTION_MS).sort((a, b) => a.undoneAt - b.undoneAt).slice(-STACK_LIMIT);
  const next = { stack, undone };
  return next;
}
function emit() {
  emitter.dispatchEvent(new Event("change"));
}
function updateState(updater) {
  const next = pruneState(updater(internalState));
  internalState = next;
  persist(next);
  emit();
}
function subscribe(listener) {
  const wrapped = () => listener();
  emitter.addEventListener("change", wrapped);
  return () => emitter.removeEventListener("change", wrapped);
}
function getClientSnapshot() {
  internalState = pruneState(internalState);
  return internalState;
}
function useOperationStore(selector) {
  return React.useSyncExternalStore(
    subscribe,
    () => selector(getClientSnapshot()),
    () => selector(DEFAULT_STATE)
  );
}
function pushOperation(meta) {
  if (typeof window === "undefined") return;
  updateState((prev) => {
    const entry = {
      ...meta,
      receivedAt: now()
    };
    const stack = prev.stack.filter((item) => item.id !== entry.id && item.undoToken !== entry.undoToken);
    stack.push(entry);
    return { stack, undone: [] };
  });
}
function markUndoSuccess(undoToken) {
  if (typeof window === "undefined") return;
  const removed = [];
  updateState((prev) => {
    const stack = prev.stack.filter((entry) => {
      if (entry.undoToken === undoToken) {
        removed.push(entry);
        return false;
      }
      return true;
    });
    const undone = removed.length ? [...prev.undone, ...removed.map((entry) => ({ ...entry, undoneAt: now() }))] : prev.undone;
    return { stack, undone };
  });
}
function markRedoConsumed(logId) {
  if (typeof window === "undefined") return;
  updateState((prev) => ({
    stack: prev.stack,
    undone: prev.undone.filter((entry) => entry.id !== logId)
  }));
}
function getLastOperation() {
  const state = getClientSnapshot();
  if (!state.stack.length) return null;
  const last = state.stack[state.stack.length - 1];
  const lastExecuted = Date.parse(last.executedAt);
  const cutoff = now() - LAST_OPERATION_TTL_MS;
  if (Number.isFinite(lastExecuted) && lastExecuted < cutoff) return null;
  if (!Number.isFinite(lastExecuted) && last.receivedAt < cutoff) return null;
  return last;
}
function useLastOperation() {
  return useOperationStore(getLastOperationFromState);
}
function getLastOperationFromState(state) {
  if (!state.stack.length) return null;
  const last = state.stack[state.stack.length - 1];
  const timestamp = now();
  const executedAt = Date.parse(last.executedAt);
  const cutoff = timestamp - LAST_OPERATION_TTL_MS;
  if (Number.isFinite(executedAt)) {
    return executedAt >= cutoff ? last : null;
  }
  return last.receivedAt >= cutoff ? last : null;
}
function useRedoCandidate() {
  return useOperationStore((state) => state.undone.length ? state.undone[state.undone.length - 1] : null);
}
function hasRedoCandidate(logId) {
  const state = getClientSnapshot();
  if (!state.undone.length) return false;
  const top = state.undone[state.undone.length - 1];
  return top.id === logId;
}
function clearAllOperations() {
  if (typeof window === "undefined") return;
  internalState = DEFAULT_STATE;
  persist(internalState);
  emit();
}
const operationStackConstants = {
  LAST_OPERATION_TTL_MS
};
export {
  clearAllOperations,
  getLastOperation,
  hasRedoCandidate,
  markRedoConsumed,
  markUndoSuccess,
  operationStackConstants,
  pushOperation,
  useLastOperation,
  useOperationStore,
  useRedoCandidate
};
//# sourceMappingURL=store.js.map
