/**
 * BackdropPortal Component
 *
 * Renders backdrop blur effects outside the CSS transform hierarchy.
 * CSS backdrop-filter doesn't work when a parent element has transform applied
 * (like translate(-50%, -50%) used for centering elements).
 *
 * This component provides a context for elements to register their backdrop
 * effects, which are then rendered in a separate layer without transform ancestors.
 */

import React, {
  createContext,
  useContext,
  useRef,
  useState,
  useCallback,
  useMemo,
} from 'react';

interface BackdropItem {
  id: string;
  style: React.CSSProperties;
  zIndex: number;
}

interface BackdropContextValue {
  registerBackdrop: (
    id: string,
    style: React.CSSProperties,
    zIndex: number,
  ) => void;
  unregisterBackdrop: (id: string) => void;
  updateBackdrop: (id: string, style: React.CSSProperties) => void;
  containerRef: React.RefObject<HTMLDivElement | null>;
}

const BackdropContext = createContext<BackdropContextValue | null>(null);

interface BackdropPortalProviderProps {
  children: React.ReactNode;
}

export const BackdropPortalProvider: React.FC<BackdropPortalProviderProps> = ({
  children,
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [backdrops, setBackdrops] = useState<Map<string, BackdropItem>>(
    new Map(),
  );

  const registerBackdrop = useCallback(
    (id: string, style: React.CSSProperties, zIndex: number) => {
      setBackdrops((prev) => new Map(prev).set(id, { id, style, zIndex }));
    },
    [],
  );

  const unregisterBackdrop = useCallback((id: string) => {
    setBackdrops((prev) => {
      const next = new Map(prev);
      next.delete(id);
      return next;
    });
  }, []);

  const updateBackdrop = useCallback(
    (id: string, style: React.CSSProperties) => {
      setBackdrops((prev) => {
        const existing = prev.get(id);
        if (!existing) return prev;
        return new Map(prev).set(id, { ...existing, style });
      });
    },
    [],
  );

  const contextValue = useMemo(
    () => ({
      registerBackdrop,
      unregisterBackdrop,
      updateBackdrop,
      containerRef,
    }),
    [registerBackdrop, unregisterBackdrop, updateBackdrop],
  );

  // Sort backdrops by zIndex for proper layering
  const sortedBackdrops = useMemo(
    () => Array.from(backdrops.values()).sort((a, b) => a.zIndex - b.zIndex),
    [backdrops],
  );

  return (
    <BackdropContext.Provider value={contextValue}>
      {/* Backdrop container - z-index: 5 keeps it above background (z-1) but below elements (z-10).
          The backdrop-filter will blur only the background behind it. */}
      <div
        ref={containerRef}
        className='absolute inset-0 pointer-events-none overflow-hidden z-5'
        style={{ zIndex: 5 }}
      >
        {sortedBackdrops.map(({ id, style }) => (
          <div key={id} className='absolute' style={style} />
        ))}
      </div>
      {children}
    </BackdropContext.Provider>
  );
};

export const useBackdropPortal = (): BackdropContextValue | null => {
  return useContext(BackdropContext);
};

export default BackdropPortalProvider;
