import { store } from "../index";
import { setLogout } from "@/state";

const g = globalThis;
if (!g.__refreshPromise) {
  g.__refreshPromise = null;
}

// let refreshPromise = null;

export const apiFetch = async (url, options = {}) => {
  try {
    const state = store.getState();
    const token = state.token;

    let res = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: token ? `Bearer ${token}` : "",
      },
      credentials: "include",
    });

    if (res.ok) return res;

    // try refresh
    console.log("refresh the token");

    // race conditions on refresh
    if (!globalThis.__refreshPromise) {
      try {
        globalThis.__refreshPromise = async () => {
          const refreshRes = await fetch(`${import.meta.env.VITE_BASE_URL}/auth/refresh`, {
            method: "POST",
            credentials: "include",
          });

          // refresh failed
          if (!refreshRes.ok) {
            store.dispatch(setLogout());
            window.location.href = "/";
            return { authError: true };
          }

          const data = await refreshRes.json();

          // save the new access token (and check for errors first, because not using setToken())
          // const newAccessToken = await refreshPromise;
          const newAccessToken = data.token;

          if (!state.user) {
            store.dispatch(setLogout());
            return { authError: true };
          }
          store.dispatch(setUser({ user: state.user, token: newAccessToken }));

          return data.token;
        };
      } catch (err) {
        console.error("refresh error:", err);
        // store.dispatch(setLogout());
        // window.location.href = "/";
        // throw err;
      } finally {
        console.log("frontend token refresh finished");
        globalThis.__refreshPromise = null;
      }
    }

    const newAccessToken = await globalThis.__refreshPromise;
    console.log(newAccessToken);

    // retry request
    res = await fetch(url, {
      ...options,
      headers: {
        ...options.headers,
        Authorization: `Bearer ${newAccessToken}`,
      },
      credentials: "include",
    });

    if (!res.ok) {
      console.log("refresh failed");
      console.log(res);
      // store.dispatch(setLogout());
      // window.location.href = "/";
      return { authError: true };
    }

    return res;
  } catch (err) {
    console.log("fetch failed");
    console.log(err);
  }
};
