import { useRequestURL } from "#app";
import { $fetch } from "ofetch";
import { useAuth } from "~/composables/useAuth";

type ApiEnvelope = {
  ok?: boolean;
  error?: { code?: string; message?: string };
};

let sessionLogoutInFlight = false;

export function isWorkpulseUnauthorized(status: number, body: unknown): boolean {
  if (status !== 401) return false;
  if (!body || typeof body !== "object") return true;
  const env = body as ApiEnvelope;
  const code = (env.error?.code ?? "").toLowerCase();
  const msg = (env.error?.message ?? "").toLowerCase();
  return (
    code === "unauthorized" ||
    code === "invalid_token" ||
    /access token|missing or invalid|not authorized|unauthorized/i.test(msg)
  );
}

function parseBody(raw: Awaited<ReturnType<typeof $fetch.raw>>): unknown {
  let body = raw._data;
  if (typeof body === "string") {
    try {
      body = JSON.parse(body);
    } catch {
      body = undefined;
    }
  }
  return body;
}

type RefreshOutcome = "ok" | "failed";

let refreshInFlight: Promise<RefreshOutcome> | null = null;
const isBrowserRuntime = () =>
  typeof window !== "undefined" && typeof document !== "undefined";

async function tryRefreshOnce(): Promise<RefreshOutcome> {
  if (!isBrowserRuntime()) return "failed";
  if (!refreshInFlight) {
    const { refreshAccessToken } = useAuth();
    refreshInFlight = (async () => ((await refreshAccessToken()) ? "ok" : "failed"))().finally(
      () => {
        refreshInFlight = null;
      }
    );
  }
  return refreshInFlight;
}

async function expireSession(): Promise<void> {
  if (!isBrowserRuntime() || sessionLogoutInFlight) return;
  sessionLogoutInFlight = true;
  try {
    const { logout } = useAuth();
    await logout();
  } finally {
    sessionLogoutInFlight = false;
  }
}

/**
 * $fetch.raw untuk API terautentikasi: coba refresh access token sekali pada 401,
 * lalu logout + redirect login jika refresh gagal.
 */
export async function workpulseApiRaw(
  url: string,
  init?: NonNullable<Parameters<typeof $fetch.raw>[1]>
) {
  const isBrowser = isBrowserRuntime();
  const resolvedUrl =
    !isBrowser && /^\/[^/]/.test(url)
      ? new URL(url, useRequestURL().origin).toString()
      : url;
  const opts: NonNullable<Parameters<typeof $fetch.raw>[1]> = {
    credentials: "include",
    ignoreResponseError: true,
    ...init
  };

  let raw = await $fetch.raw(resolvedUrl, opts);
  if (!isWorkpulseUnauthorized(raw.status, parseBody(raw))) return raw;

  // SSR tidak punya konteks Nuxt composable yang stabil untuk useAuth/useCookie.
  // Hindari refresh otomatis di server agar tidak memicu "Nuxt instance unavailable".
  if (!isBrowser) return raw;

  const refreshed = await tryRefreshOnce();
  if (refreshed === "ok") {
    raw = await $fetch.raw(resolvedUrl, opts);
    if (!isWorkpulseUnauthorized(raw.status, parseBody(raw))) return raw;
  }

  return raw;
}
