"use client";

// src/lib/persisted-state.ts
import * as React from "react";
var EXXAT_STORAGE_PREFIX = "exxat-ds:";
var DEFAULT_DEBOUNCE_MS = 400;
var isBrowser = () => typeof window !== "undefined";
function getDriverImpl(driver) {
  if (!isBrowser()) return null;
  try {
    return driver === "session" ? window.sessionStorage : window.localStorage;
  } catch {
    return null;
  }
}
function namespacedKey(key) {
  return key.startsWith(EXXAT_STORAGE_PREFIX) ? key : `${EXXAT_STORAGE_PREFIX}${key}`;
}
function getStorageItem(key, driver = "local") {
  const store = getDriverImpl(driver);
  if (!store) return null;
  try {
    return store.getItem(namespacedKey(key));
  } catch {
    return null;
  }
}
function setStorageItem(key, value, driver = "local") {
  const store = getDriverImpl(driver);
  if (!store) return;
  try {
    store.setItem(namespacedKey(key), value);
  } catch {
  }
}
function removeStorageItem(key, driver = "local") {
  const store = getDriverImpl(driver);
  if (!store) return;
  try {
    store.removeItem(namespacedKey(key));
  } catch {
  }
}
var debounceTimers = /* @__PURE__ */ new Map();
function scheduleStorageWrite(key, value, options = {}) {
  if (!isBrowser()) return;
  const { debounceMs = DEFAULT_DEBOUNCE_MS, driver = "local" } = options;
  const fullKey = namespacedKey(key);
  const prev = debounceTimers.get(fullKey);
  if (prev) clearTimeout(prev);
  const t = setTimeout(() => {
    debounceTimers.delete(fullKey);
    setStorageItem(key, value, driver);
  }, debounceMs);
  debounceTimers.set(fullKey, t);
}
function flushPendingStorageWrites() {
  if (!isBrowser()) return;
  for (const [, timer] of debounceTimers) {
    clearTimeout(timer);
  }
  debounceTimers.clear();
}
function subscribeToStorageKey(key, listener) {
  if (!isBrowser()) return () => {
  };
  const fullKey = namespacedKey(key);
  const handler = (e) => {
    if (e.key !== fullKey) return;
    listener(e.newValue);
  };
  window.addEventListener("storage", handler);
  return () => window.removeEventListener("storage", handler);
}
function clearAllPersistedState(driver = "local") {
  const store = getDriverImpl(driver);
  if (!store) return;
  try {
    const toRemove = [];
    for (let i = 0; i < store.length; i++) {
      const k = store.key(i);
      if (k && k.startsWith(EXXAT_STORAGE_PREFIX)) toRemove.push(k);
    }
    for (const k of toRemove) store.removeItem(k);
  } catch {
  }
}
function listPersistedKeys(driver = "local") {
  const store = getDriverImpl(driver);
  if (!store) return [];
  try {
    const out = [];
    for (let i = 0; i < store.length; i++) {
      const k = store.key(i);
      if (k && k.startsWith(EXXAT_STORAGE_PREFIX)) out.push(k);
    }
    return out;
  } catch {
    return [];
  }
}
var defaultOptions = {
  driver: "local",
  version: 1,
  debounceMs: DEFAULT_DEBOUNCE_MS,
  syncAcrossTabs: true
};
function readPersisted(key, defaultValue, opts) {
  const raw = getStorageItem(key, opts.driver);
  if (raw == null) return defaultValue;
  try {
    const parsed = JSON.parse(raw);
    if (parsed != null && typeof parsed === "object" && "v" in parsed && "d" in parsed) {
      const env = parsed;
      if (env.v === opts.version) {
        return env.d;
      }
      if (opts.migrate) {
        const migrated = opts.migrate(env.d, env.v);
        if (migrated !== void 0) return migrated;
      }
      return defaultValue;
    }
  } catch {
  }
  if (opts.deserialize) {
    const out = opts.deserialize(raw);
    if (out !== void 0) return out;
  }
  return defaultValue;
}
function writePersisted(key, value, opts) {
  const serialize = opts.serialize ?? ((v) => JSON.stringify({ v: opts.version, d: v }));
  const payload = serialize(value);
  if (opts.debounceMs <= 0) {
    setStorageItem(key, payload, opts.driver);
  } else {
    scheduleStorageWrite(key, payload, { debounceMs: opts.debounceMs, driver: opts.driver });
  }
}
function usePersistedState(key, defaultValue, options) {
  const merged = { ...defaultOptions, ...options };
  const optsRef = React.useRef(merged);
  optsRef.current = merged;
  const enabled = key.length > 0;
  const [value, setValue] = React.useState(
    () => enabled ? readPersisted(key, defaultValue, optsRef.current) : defaultValue
  );
  const hydratedRef = React.useRef(false);
  React.useLayoutEffect(() => {
    if (hydratedRef.current) return;
    hydratedRef.current = true;
    if (!enabled) return;
    const persisted = readPersisted(key, defaultValue, optsRef.current);
    setValue((prev) => Object.is(prev, persisted) ? prev : persisted);
  }, [key, enabled]);
  React.useEffect(() => {
    if (!hydratedRef.current) return;
    if (!enabled) return;
    writePersisted(key, value, optsRef.current);
  }, [key, value, enabled]);
  React.useEffect(() => {
    if (!enabled) return;
    if (!optsRef.current.syncAcrossTabs) return;
    return subscribeToStorageKey(key, () => {
      const next = readPersisted(key, defaultValue, optsRef.current);
      setValue(next);
    });
  }, [key, enabled]);
  const clear = React.useCallback(() => {
    if (enabled) removeStorageItem(key, optsRef.current.driver);
    setValue(defaultValue);
  }, [key, enabled]);
  return [value, setValue, clear];
}
export {
  DEFAULT_DEBOUNCE_MS,
  EXXAT_STORAGE_PREFIX,
  clearAllPersistedState,
  flushPendingStorageWrites,
  getStorageItem,
  listPersistedKeys,
  namespacedKey,
  removeStorageItem,
  scheduleStorageWrite,
  setStorageItem,
  subscribeToStorageKey,
  usePersistedState
};
//# sourceMappingURL=persisted-state.js.map