/**
 * API 客户端配置
 * 封装 Axios 实例，配置拦截器和 Token 管理
 */
import axios, { AxiosError, InternalAxiosRequestConfig } from "axios";
import { message } from "antd";
import { useAuthStore } from "@/store/authStore";
import { refreshAccessToken } from "./auth";

// 创建 Axios 实例
const apiClient = axios.create({
  baseURL: "/api/v1",
  timeout: 10000,
  headers: {
    "Content-Type": "application/json",
  },
});

// ── Token 刷新队列 ─────────────────────────────────────────
let isRefreshing = false;
let failedQueue: Array<{
  resolve: (value?: unknown) => void;
  reject: (reason?: unknown) => void;
}> = [];

const processQueue = (error: unknown | null, token: string | null = null) => {
  failedQueue.forEach((prom) => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });
  failedQueue = [];
};

// 请求拦截器：添加 Token
apiClient.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const token = localStorage.getItem("access_token");
    if (token && config.headers) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error: AxiosError) => {
    return Promise.reject(error);
  },
);

// 响应拦截器：统一错误提示 + 401 自动刷新 Token
apiClient.interceptors.response.use(
  (response) => response,
  async (
    error: AxiosError<{ detail?: string; message?: string; msg?: string }>,
  ) => {
    const originalRequest = error.config as InternalAxiosRequestConfig & {
      _retry?: boolean;
    };

    // 401 → 尝试刷新 Token
    if (
      error.response?.status === 401 &&
      originalRequest &&
      !originalRequest._retry
    ) {
      const refreshToken = useAuthStore.getState().refreshToken;

      // 无 refresh_token → 直接登出
      if (!refreshToken) {
        useAuthStore.getState().clearAuth();
        window.location.href = "/";
        return Promise.reject(error);
      }

      // 已在刷新中 → 排队等待
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        }).then((token) => {
          if (originalRequest.headers) {
            originalRequest.headers.Authorization = `Bearer ${token}`;
          }
          return apiClient(originalRequest);
        });
      }

      originalRequest._retry = true;
      isRefreshing = true;

      try {
        const data = await refreshAccessToken(refreshToken);
        const newAccessToken = data.access_token;
        const newRefreshToken = data.refresh_token ?? refreshToken;

        // 更新 Zustand + localStorage
        useAuthStore
          .getState()
          .setAuth(
            useAuthStore.getState().user!,
            newAccessToken,
            newRefreshToken,
          );

        // 处理排队的请求
        processQueue(null, newAccessToken);

        // 重试原始请求
        if (originalRequest.headers) {
          originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
        }
        return apiClient(originalRequest);
      } catch (refreshError) {
        // 刷新失败 → 登出
        processQueue(refreshError, null);
        useAuthStore.getState().clearAuth();
        window.location.href = "/";
        return Promise.reject(refreshError);
      } finally {
        isRefreshing = false;
      }
    }

    // 提取后端返回的错误信息（detail / message / msg）
    const data = error.response?.data;
    const serverMsg = data?.detail || data?.message || data?.msg;
    let handled = false;

    if (error.code === "ECONNABORTED" || error.message?.includes("timeout")) {
      message.error("请求超时，请检查网络后重试");
      handled = true;
    } else if (!error.response) {
      message.error("网络连接异常，请检查网络设置");
      handled = true;
    } else if (serverMsg) {
      message.error(serverMsg);
      handled = true;
    } else {
      const status = error.response?.status;
      if (status === 413) {
        message.error("文件过大，请缩小后重试");
        handled = true;
      } else if (status === 415) {
        message.error("不支持的文件格式");
        handled = true;
      } else if (status === 503) {
        message.error("服务暂不可用，请稍后再试");
        handled = true;
      } else if (status && status >= 500) {
        message.error("服务器繁忙，请稍后再试");
        handled = true;
      }
      // 其他 4xx 且无具体信息时不弹通用提示，由各组件自行处理
    }

    // 标记已展示过提示，组件 onError 可据此跳过重复 toast
    if (handled) {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (error as any).__msgShown = true;
    }

    return Promise.reject(error);
  },
);

export default apiClient;
