import React, {
  createContext,
  ReactNode,
  RefObject,
  useCallback,
  useContext,
  useMemo,
  useReducer,
  useRef,
} from 'react';
import { StyleSheet, View } from 'react-native';

interface TooltipPortalContextValue {
  register: (id: string, content: ReactNode) => void;
  unregister: (id: string, immediate?: boolean) => void;
  portals: Map<string, ReactNode>;
  hostRef: RefObject<View | null>;
}

const TooltipPortalContext = createContext<TooltipPortalContextValue | null>(
  null,
);

export const TooltipPortalProvider: React.FC<{ children: ReactNode }> = ({
  children,
}) => {
  // Use ref for synchronous updates + reducer for manual re-renders
  const portalsRef = useRef<Map<string, ReactNode>>(new Map());
  const hostRef = useRef<View>(null);
  const [updateCounter, forceUpdate] = useReducer((x: number) => x + 1, 0);
  const pendingUpdateRef = useRef<any>(null);

  const register = useCallback((id: string, content: ReactNode) => {
    portalsRef.current.set(id, content);
    forceUpdate(); // Trigger re-render to show new content
  }, []);

  const unregister = useCallback((id: string, immediate = false) => {
    const hasItem = portalsRef.current.has(id);
    if (!hasItem) return; // Already removed

    portalsRef.current.delete(id);

    // Clear any pending updates
    if (pendingUpdateRef.current) {
      clearTimeout(pendingUpdateRef.current);
      pendingUpdateRef.current = null;
    }

    if (immediate) {
      forceUpdate();
    } else {
      // Debounce normal updates to avoid excessive re-renders
      pendingUpdateRef.current = setTimeout(() => {
        forceUpdate();
        pendingUpdateRef.current = null;
      }, 0);
    }
  }, []);

  const contextValue = useMemo(
    () => ({ register, unregister, portals: portalsRef.current, hostRef }),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [register, unregister, updateCounter]
  );


  return (
    <TooltipPortalContext.Provider value={contextValue}>
      {children}
    </TooltipPortalContext.Provider>
  );
};

export const TooltipPortalHost: React.FC = () => {
  const context = useContext(TooltipPortalContext);

  if (!context) {
    if (__DEV__) {
      console.warn(
        'TooltipPortalHost must be used within TooltipPortalProvider',
      );
    }
    return null;
  }

  const { portals, hostRef } = context;

  return (
    <View ref={hostRef} style={styles.hostContainer} pointerEvents="box-none">
      {Array.from(portals.entries()).map(([id, content]) => (
        <React.Fragment key={id}>{content}</React.Fragment>
      ))}
    </View>
  );
};

export const useTooltipPortal = () => {
  const context = useContext(TooltipPortalContext);

  if (!context) {
    if (__DEV__) {
      console.warn(
        'useTooltipPortal must be used within TooltipPortalProvider. Tooltips may not appear correctly.',
      );
    }
    // Return no-op functions if context is missing
    return {
      register: () => { },
      unregister: () => { },
      hostRef: null,
    };
  }

  return context;
};

const styles = StyleSheet.create({
  hostContainer: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    zIndex: 9999,
  },
});
