"use client";

import { createContext, useContext, useEffect, useMemo, useState } from "react";
import GlobalLoader from "@/components/ui/GlobalLoader";

type ApiLoadingContextValue = {
  isLoading: boolean;
};

const ApiLoadingContext = createContext<ApiLoadingContextValue>({ isLoading: false });

export function ApiLoadingProvider({ children }: { children: React.ReactNode }) {
  const [requestCount, setRequestCount] = useState(0);

  useEffect(() => {
    if (typeof window === "undefined") return;

    const globalWindow = window as Window & {
      __oxyfinz_fetch_wrapped__?: boolean;
      __oxyfinz_original_fetch__?: typeof window.fetch;
    };

    if (globalWindow.__oxyfinz_fetch_wrapped__) {
      return;
    }

    globalWindow.__oxyfinz_original_fetch__ =
      globalWindow.__oxyfinz_original_fetch__ ?? globalWindow.fetch;
    const baseFetch = globalWindow.__oxyfinz_original_fetch__;

    let mounted = true;

    const wrappedFetch: typeof window.fetch = async (...args) => {
      if (!mounted) {
        return baseFetch(...args);
      }
      // Defer state update to avoid render-phase updates
      queueMicrotask(() => {
        if (mounted) {
          setRequestCount((prev) => prev + 1);
        }
      });
      try {
        const response = await baseFetch(...args);
        return response;
      } finally {
        if (mounted) {
          queueMicrotask(() => {
            if (mounted) {
              setRequestCount((prev) => Math.max(prev - 1, 0));
            }
          });
        }
      }
    };

    globalWindow.fetch = wrappedFetch;
    globalWindow.__oxyfinz_fetch_wrapped__ = true;

    return () => {
      mounted = false;
      globalWindow.fetch = baseFetch;
      globalWindow.__oxyfinz_fetch_wrapped__ = false;
    };
  }, []);

  const value = useMemo(
    () => ({
      isLoading: requestCount > 0,
    }),
    [requestCount]
  );

  return (
    <ApiLoadingContext.Provider value={value}>
      {children}
      {value.isLoading && <GlobalLoader />}
    </ApiLoadingContext.Provider>
  );
}

export const useApiLoading = () => useContext(ApiLoadingContext);
