import { useSyncExternalStore } from "react";

// A minimal observable value shared across React components AND non-React code (the api
// layer, websocket handlers, etc.). Replaces the hand-rolled `listeners`/`subscribe`/`emit`
// triad that several modules each re-implemented slightly differently.
export interface Store<T> {
  get(): T;
  set(next: T | ((prev: T) => T)): void;
  subscribe(listener: () => void): () => void;
  /** Subscribe from a component; re-renders on every change. */
  use(): T;
}

export function createStore<T>(initial: T): Store<T> {
  let value = initial;
  const listeners = new Set<() => void>();
  const get = () => value;
  const subscribe = (l: () => void) => {
    listeners.add(l);
    return () => {
      listeners.delete(l);
    };
  };
  return {
    get,
    set(next) {
      value = typeof next === "function" ? (next as (p: T) => T)(value) : next;
      listeners.forEach((l) => l());
    },
    subscribe,
    use: () => useSyncExternalStore(subscribe, get, get),
  };
}
