/**
 * loadingOverlayStore — global, cross-island UI state for the full-screen LoadingOverlay.
 *
 * Multideal hard rule: spinners NEVER render inline inside buttons. Long async work shows
 * a full-viewport overlay instead. Any component (across any Astro island) can call
 * `useLoadingOverlay().show(label)` / `.hide()` and the single mounted `<LoadingOverlay />`
 * inside HydratedIsland reacts.
 *
 * Concurrent work is supported via a counter — every `show()` increments, every `hide()`
 * decrements. Overlay is visible while count > 0. The most recent label wins.
 */

import { create } from 'zustand';

interface LoadingOverlayState {
  /** Active concurrent show() calls. Overlay visible iff count > 0. */
  count: number;
  /** Latest label passed to show(); undefined uses default i18n label. */
  label?: string;
  /** Increment count and (optionally) update label. */
  show: (label?: string) => void;
  /** Decrement count; clears label when count reaches 0. */
  hide: () => void;
}

export const useLoadingOverlayStore = create<LoadingOverlayState>((set) => ({
  count: 0,
  label: undefined,
  show: (label) =>
    set((s) => ({
      count: s.count + 1,
      label: label ?? s.label,
    })),
  hide: () =>
    set((s) => {
      const next = Math.max(0, s.count - 1);
      return {
        count: next,
        label: next === 0 ? undefined : s.label,
      };
    }),
}));

/**
 * useLoadingOverlay — convenience hook returning stable show/hide actions.
 *
 * @example
 * const { show, hide } = useLoadingOverlay();
 * const onSubmit = async () => {
 *   show(t('saving'));
 *   try { await save(); } finally { hide(); }
 * };
 */
export function useLoadingOverlay() {
  const show = useLoadingOverlayStore((s) => s.show);
  const hide = useLoadingOverlayStore((s) => s.hide);
  return { show, hide };
}
