import { createContext, type ReactNode, useCallback, useContext, useEffect, useMemo, useRef } from 'react';

import type { GlobalStateStoreType } from './GlobalStateStore.types';

import { GetGlobalState, GlobalStateStore } from './GlobalStateStore';


interface GlobalStateStoreContextValue {
  fetchData: (url?: string) => Promise<void>;
  getState: () => GlobalStateStoreType;
  refetch: () => Promise<void>;
}

const GlobalStateStoreContext = createContext<GlobalStateStoreContextValue | null>(null);


interface GlobalStateStoreProviderProps {
  apiURL?: string;
  autoFetch?: boolean;
  children: ReactNode;
  fetchOnMount?: boolean;
  throttleMs?: number;
}

export function GlobalStateStoreProvider({
  apiURL,
  autoFetch = true,
  children,
  fetchOnMount = true,
  throttleMs = 0,
}: GlobalStateStoreProviderProps) {
  const lastFetchTime = useRef<number>(0);
  const fetchInProgress = useRef<boolean>(false);
  const mounted = useRef<boolean>(false);


  const throttledFetch = useCallback(
    async (url?: string) => {
      const now = Date.now();
      const timeSinceLastFetch = now - lastFetchTime.current;

      if (fetchInProgress.current) {
        return;
      }

      if (throttleMs > 0 && timeSinceLastFetch < throttleMs) {
        return;
      }

      try {
        fetchInProgress.current = true;
        lastFetchTime.current = now;
        await GlobalStateStore.getState().fetchData(url);
      } finally {
        fetchInProgress.current = false;
      }
    },
    [throttleMs]
  );

  const refetch = useCallback(async () => {
    await throttledFetch();
  }, [throttledFetch]);

  useEffect(() => {
    if (apiURL) {
      GlobalStateStore.getState().setApiURL(apiURL);
    }
  }, [apiURL]);

  useEffect(() => {
    if (!mounted.current) {
      mounted.current = true;

      if (autoFetch && fetchOnMount) {
        throttledFetch(apiURL).catch((e) => {
          console.error('Failed to fetch on mount:', e);
        });
      }
    }
  }, [apiURL, autoFetch, fetchOnMount, throttledFetch]);

  const context = useMemo(() => {
    return {
      fetchData: throttledFetch,
      getState: GetGlobalState,
      refetch,
    };
  }, [throttledFetch, refetch]);

  

  return (
    <GlobalStateStoreContext.Provider value={context}>
      {children}
    </GlobalStateStoreContext.Provider>
  );
}

// eslint-disable-next-line react-refresh/only-export-components
export function useGlobalStateStoreContext(): GlobalStateStoreContextValue {
  const context = useContext(GlobalStateStoreContext);
  if (!context) {
    throw new Error('useGlobalStateStoreContext must be used within GlobalStateStoreProvider');
  }
  return context;
}
