/**
 * axios 实例 & JWT 拦截器。
 *
 * - tenantApi：baseURL /api/tenant，用于租户端 API
 * - adminApi：baseURL /api/admin，用于管理端 API
 * - 请求拦截器：自动从 localStorage 读取 access_token 附加 Authorization header
 * - 响应拦截器：401 时用 refresh_token 刷新，刷新失败重定向 /login
 * - 并发刷新保护：多个 401 只触发一次 refresh，其余排队
 * - 响应解包：{ code: 0, data } → 提取 data
 */

import axios, {
  type AxiosError,
  type AxiosInstance,
  type AxiosRequestConfig,
  type InternalAxiosRequestConfig,
} from "axios";

/* ------------------------------------------------------------------ */
/*  常量                                                               */
/* ------------------------------------------------------------------ */

const ACCESS_TOKEN_KEY = "access_token";
const REFRESH_TOKEN_KEY = "refresh_token";

/* ------------------------------------------------------------------ */
/*  刷新状态（两个实例共享）                                            */
/* ------------------------------------------------------------------ */

let isRefreshing = false;
let pendingQueue: {
  resolve: (token: string) => void;
  reject: (err: unknown) => void;
}[] = [];

function processPendingQueue(token: string | null, error: unknown) {
  pendingQueue.forEach(({ resolve, reject }) => {
    if (token) resolve(token);
    else reject(error);
  });
  pendingQueue = [];
}

function clearTokensAndRedirect() {
  localStorage.removeItem(ACCESS_TOKEN_KEY);
  localStorage.removeItem(REFRESH_TOKEN_KEY);
  if (window.location.pathname !== "/login") {
    window.location.href = "/login";
  }
}

/* ------------------------------------------------------------------ */
/*  拦截器工厂                                                         */
/* ------------------------------------------------------------------ */

function attachInterceptors(instance: AxiosInstance) {
  // 请求拦截器 — 附加 JWT
  instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
    const token = localStorage.getItem(ACCESS_TOKEN_KEY);
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  });

  // 响应拦截器 — 解包 + 401 刷新
  instance.interceptors.response.use(
    (response) => {
      // 后端 ResponseWrapperMiddleware: { code: 0, data } → 提取 data
      const body = response.data;
      if (body && typeof body === "object" && "code" in body && "data" in body) {
        response.data = body.data;
      }
      return response;
    },
    async (error: AxiosError) => {
      const originalRequest = error.config as AxiosRequestConfig & {
        _retried?: boolean;
      };

      if (
        error.response?.status !== 401 ||
        !originalRequest ||
        originalRequest._retried
      ) {
        return Promise.reject(error);
      }

      // 刷新端点本身 401 → 不递归
      if (originalRequest.url?.includes("/auth/refresh")) {
        clearTokensAndRedirect();
        return Promise.reject(error);
      }

      // 已有刷新在飞 → 排队
      if (isRefreshing) {
        return new Promise<string>((resolve, reject) => {
          pendingQueue.push({ resolve, reject });
        }).then((newToken) => {
          originalRequest.headers = {
            ...originalRequest.headers,
            Authorization: `Bearer ${newToken}`,
          };
          originalRequest._retried = true;
          return instance(originalRequest);
        });
      }

      // 发起刷新
      isRefreshing = true;
      originalRequest._retried = true;

      const refreshToken = localStorage.getItem(REFRESH_TOKEN_KEY);
      if (!refreshToken) {
        isRefreshing = false;
        processPendingQueue(null, error);
        clearTokensAndRedirect();
        return Promise.reject(error);
      }

      try {
        // ResponseWrapperMiddleware 包装响应为 { code: 0, data: { access_token, refresh_token } }
        const resp = await axios.post<{
          code: number;
          data: { access_token: string; refresh_token: string };
        }>("/api/tenant/auth/refresh", { refresh_token: refreshToken });

        const tokens = resp.data.data;
        localStorage.setItem(ACCESS_TOKEN_KEY, tokens.access_token);
        localStorage.setItem(REFRESH_TOKEN_KEY, tokens.refresh_token);
        processPendingQueue(tokens.access_token, null);

        originalRequest.headers = {
          ...originalRequest.headers,
          Authorization: `Bearer ${tokens.access_token}`,
        };
        return instance(originalRequest);
      } catch (refreshError) {
        processPendingQueue(null, refreshError);
        clearTokensAndRedirect();
        return Promise.reject(refreshError);
      } finally {
        isRefreshing = false;
      }
    },
  );
}

/* ------------------------------------------------------------------ */
/*  实例                                                               */
/* ------------------------------------------------------------------ */

/** 租户端 API（/api/tenant） */
export const tenantApi = axios.create({ baseURL: "/api/tenant" });
attachInterceptors(tenantApi);

/** 管理端 API（/api/admin） */
export const adminApi = axios.create({ baseURL: "/api/admin" });
attachInterceptors(adminApi);
