import { store } from "../index";
import { setLogout, setToken } from "@/state";
let isRefreshing = false;
let refreshPromise = null;
const triggerRefresh = async () => {
  // ensure only one refresh fetch is started
  console.log("refreshing");
  if (!isRefreshing) {
    isRefreshing = true;
    refreshPromise = (async () => {
      try {
        const refreshRes = await fetch(`${import.meta.env.VITE_BASE_URL}/auth/refresh`, {
          method: "POST",
          credentials: "include",
        });
        if (!refreshRes.ok) {
          // refresh failed -> force logout
          store.dispatch(setLogout());
          window.location.href = "/";
          throw new Error("refresh failed");
        }
        const data = await refreshRes.json();
        // store new access token
        store.dispatch(setToken({ token: data.token }));
        return data.token;
      } finally {
        // clear the flag only after promise settles (success or failure)
        isRefreshing = false;
      }
    })();
  }
  return refreshPromise;
};
export const apiFetch = async (url, options = {}) => {
  try {
    const state = store.getState();
    let token = state.token;

    const makeRequest = (authToken) =>
      fetch(url, {
        ...options,
        headers: {
          ...options.headers,
          Authorization: authToken ? `Bearer ${authToken}` : "",
        },
        credentials: "include",
      });

    // If a refresh is underway, wait for it so we don't hit server with stale token
    if (isRefreshing && refreshPromise) {
      console.log("wait for refresh");
      const freshToken = await refreshPromise.catch(() => null);
      if (!freshToken) {
        // refresh failed; logout handled in triggerRefresh
        return { authError: true };
      }
      token = freshToken;
    }

    // Perform the request with the (possibly fresh) token
    let res = await makeRequest(token);

    // If successful, return
    if (res.ok) return res;

    // If error not auth, just return response
    if (res.status !== 401 && res.status !== 403) return res;

    // On 401/403: attempt refresh (single-flight) and then retry
    const newToken = await triggerRefresh().catch(() => null);
    if (!newToken) {
      // refresh failed and triggerRefresh already handled logout/redirect
      return { authError: true };
    }

    // Retry original request with new token
    res = await makeRequest(newToken);
    return res;
  } catch (err) {
    store.dispatch(setLogout());
    window.location.href = "/";
    console.log("error", err);
    return { authError: true };
  }
};
