import axios, { AxiosHeaders, type InternalAxiosRequestConfig } from "axios";
import { config } from "@config/config";
import { signOut } from "next-auth/react";
import { useAuthStore } from "@/store/authStore";
import {
  applyAuthContextHeaders,
  type AuthContextHeaderOptions,
} from "@/lib/requestHeaders";

export const API_URL = config.BACKEND_URL;

export const api = axios.create({
  baseURL: API_URL,
});

let isSigningOut = false;

export const resolveRequestUrl = (request: {
  baseURL?: string;
  url?: string;
}) => {
  const requestUrl = request.url ?? "";
  if (/^([a-z][a-z\d+\-.]*:)?\/\//i.test(requestUrl)) {
    return requestUrl;
  }

  const baseURL = request.baseURL ?? "";
  if (!baseURL || !requestUrl) {
    return `${baseURL}${requestUrl}`;
  }

  return `${baseURL.replace(/\/+$/, "")}/${requestUrl.replace(/^\/+/, "")}`;
};

export interface ApiRequestConfig
  extends InternalAxiosRequestConfig,
    AuthContextHeaderOptions {}

api.interceptors.request.use(async (request: ApiRequestConfig) => {
  const headers = new Headers(
    request.headers
      ? AxiosHeaders.from(request.headers).toJSON() as Record<string, string>
      : undefined,
  );
  await applyAuthContextHeaders(resolveRequestUrl(request), headers, request);

  request.headers = AxiosHeaders.from(Object.fromEntries(headers.entries()));

  return request;
});

api.interceptors.response.use(
  (response) => {
    if (
      response.data &&
      typeof response.data === "object" &&
      Array.isArray(response.data.items) &&
      typeof response.data.total === "number"
    ) {
      response.data = response.data.items;
    }
    return response;
  },
  async (error) => {
    if (error?.response?.status === 401 && typeof window !== "undefined") {
      useAuthStore.getState().setAccessToken(null);
      if (!isSigningOut) {
        isSigningOut = true;
        await signOut({ redirect: true, callbackUrl: "/login" });
      }
    }
    return Promise.reject(error);
  },
);
