import { useCallback, useEffect, useRef } from 'react';
import { useWixPatternsContainer } from '@wix/bex-core/react';

export type OpenCollectionOverlay = (onReturnToForeground?: () => void) => void;

/**
 * Builds an opener that navigates to a collection (by id) as an overlay on top
 * of the current page, and invokes `onReturnToForeground` once the overlay
 * closes and the page returns to the foreground.
 *
 * Must be called from a component that outlives the inline cell editor (e.g. a
 * cell type's `EditWrapper`): opening the overlay typically commits/unmounts
 * the editor, so the layer-state subscription is owned here and disposed only
 * on this owner's unmount (and before re-opening). The editor passes the
 * refresh it wants to run on return as `onReturnToForeground` when it calls the
 * opener, since the editor — not this owner — holds the data to refresh.
 *
 * Returns `undefined` when the host can't navigate (no `collectionId`,
 * `navigateTo`, or page location).
 */
export function useOpenCollectionOverlay({
  collectionId,
}: {
  collectionId: string | undefined;
}): OpenCollectionOverlay | undefined {
  const container = useWixPatternsContainer();
  const pageLocation = container.usePageLocation?.();
  const navigateTo = container.navigateTo;
  const onLayerStateChange = container.onLayerStateChange;

  // The subscription is owned by this (stable) component, not the editor that
  // triggers it, so it survives the editor unmounting when the overlay opens
  // and is disposed on this owner's unmount (or before re-opening).
  const subscriptionRef = useRef<{ remove: () => void } | null>(null);
  useEffect(
    () => () => {
      subscriptionRef.current?.remove();
      subscriptionRef.current = null;
    },
    [],
  );

  const open = useCallback<OpenCollectionOverlay>(
    (onReturnToForeground) => {
      if (!collectionId || !navigateTo || !pageLocation) {
        return;
      }
      // Preserve the current route (pathname, existing query params, hash) and
      // only swap in the referenced collectionId, so nested routes and required
      // query state survive the navigation.
      const params = new URLSearchParams(pageLocation.search);
      params.set('collectionId', collectionId);
      navigateTo({
        pageId: pageLocation.pageId,
        relativeUrl: `${pageLocation.pathname}?${params.toString()}${
          pageLocation.hash ?? ''
        }`,
        displayMode: 'overlay',
        history: 'replace',
      });

      subscriptionRef.current?.remove();
      subscriptionRef.current =
        onLayerStateChange?.((newState) => {
          if (newState === 'foreground') {
            subscriptionRef.current?.remove();
            subscriptionRef.current = null;
            onReturnToForeground?.();
          }
        }) ?? null;
    },
    [collectionId, navigateTo, pageLocation, onLayerStateChange],
  );

  const canOpen = Boolean(collectionId && navigateTo && pageLocation);
  return canOpen ? open : undefined;
}
