/**
 * axios 实例 & JWT 拦截器。
 *
 * - 请求拦截器：自动从 localStorage 读取 access_token 并附加 Authorization header
 * - 响应拦截器：遇到 401 时尝试用 refresh_token 刷新，刷新失败则清除令牌并跳转 /login
 * - 并发刷新保护：多个请求同时 401 时只触发一次 refresh，其余排队等待
 */

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

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

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

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

export const apiClient = axios.create({
  baseURL: "/api",
});

/* ------------------------------------------------------------------ */
/*  请求拦截器 — 附加 JWT                                              */
/* ------------------------------------------------------------------ */

apiClient.interceptors.request.use((config: InternalAxiosRequestConfig) => {
  const token = localStorage.getItem(ACCESS_TOKEN_KEY);
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

/* ------------------------------------------------------------------ */
/*  响应拦截器 — 401 自动刷新                                          */
/* ------------------------------------------------------------------ */

/** 是否正在刷新中 */
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 = [];
}

apiClient.interceptors.response.use(
  (response) => {
    // 后端 ResponseWrapperMiddleware 将成功响应包装为 { code: 0, data: <原始body> }
    // 此处统一解包，使上层代码无需感知包装层
    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;
    };

    // 非 401、无原始请求、或已重试过 → 直接抛出
    if (
      error.response?.status !== 401 ||
      !originalRequest ||
      originalRequest._retried
    ) {
      return Promise.reject(error);
    }

    // 刷新端点本身 401 → 不再递归刷新
    if (originalRequest.url === "/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 apiClient(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 {
      // 用独立 axios 调用避免被自身拦截器干扰
      // ResponseWrapperMiddleware 包装响应为 { code: 0, data: { access_token, refresh_token } }
      const resp = await axios.post<{
        code: number;
        data: { access_token: string; refresh_token: string };
      }>("/api/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 apiClient(originalRequest);
    } catch (refreshError) {
      processPendingQueue(null, refreshError);
      clearTokensAndRedirect();
      return Promise.reject(refreshError);
    } finally {
      isRefreshing = false;
    }
  },
);

/* ------------------------------------------------------------------ */
/*  辅助                                                               */
/* ------------------------------------------------------------------ */

function clearTokensAndRedirect() {
  localStorage.removeItem(ACCESS_TOKEN_KEY);
  localStorage.removeItem(REFRESH_TOKEN_KEY);

  // 派发自定义事件，让 authStore 监听并重置状态
  // 避免直接 import authStore 导致循环依赖
  window.dispatchEvent(new Event("auth:force-logout"));

  // 避免在登录页反复跳转
  if (window.location.pathname !== "/login") {
    window.location.href = "/login";
  }
}
