import axios, { type InternalAxiosRequestConfig, type AxiosResponse } from "axios";
import qs from "qs";
import { useUserStoreHook } from "@/store/modules/user";
import { ResultEnum } from "@/enums/ResultEnum";
import { getToken } from "@/utils/auth";
import router from "@/router";
// 创建 axios 实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 1000 * 60 * 3,
  headers: { "Content-Type": "application/json;charset=utf-8", platformType: 'WEB' },
  paramsSerializer: (params) => qs.stringify(params),
});

/**
 * 格式化错误信息msg
 */
function formatErrorMsg(error: string) {
  // 1. 获取原始提示文本（兜底空字符串避免报错）
  const originMsg = error
  // 2. 定义要匹配的前缀
  const exceptionPrefix = "Exception:";
  // 3. 判断是否包含目标前缀
  if (originMsg.includes(exceptionPrefix)) {
    // 截取前缀后的内容 → 去除首尾空格 → 限制最大20个字符
    return originMsg
      .slice(
        originMsg.indexOf(exceptionPrefix) +
        exceptionPrefix.length
      )
      .trim()
      .slice(0, 20);
  } else {
    // 不包含则按原逻辑截取前20个字符
    return originMsg.slice(0, 20);
  }
}

// 请求拦截器
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    const accessToken = getToken();
    // 如果 Authorization 设置为 no-auth，则不携带 Token，用于登录、刷新 Token 等接口
    if (config.headers.Authorization !== "no-auth" && accessToken) {
      config.headers.token = accessToken;
    } else {
      delete config.headers.token;
    }
    // config.headers.shopId = config.headers.shopId || localStorage.getItem("branch_shopId");
    config.headers.shopId = config.headers.shopId || useUserStoreHook().userInfo.id;
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {

    // 如果响应是二进制流，则直接返回，用于下载文件、Excel 导出等
    if (response.config.responseType === "blob") {
      return response.data;
    }

    const { code, data, msg } = response.data;
    if (data) {
      // 处理后台返回分页相关数据为字符串类型时，elementui组件警告
      const kes = ['pageNumber', 'pageSize', 'totalPage', 'totalRow'];
      const keys = Object.keys(data);
      for (let i of kes) {
        if (keys.includes(i)) {
          data[i] = data[i] * 1;
        }
      }
    }
    if (code === ResultEnum.SUCCESS || code === undefined || code === null) {
      return data ? data : response.data;
    }

    if (code === ResultEnum.ACCESS_TOKEN_INVALID) {
      ElNotification({
        title: "提示",
        message: "您的会话已过期，请重新登录",
        type: "info",
      });
      useUserStoreHook()
        .clearUserData()
        .then(() => {
          router.push("/login");
        });
      return;
    }
    ElMessage.error(formatErrorMsg(msg || "Error"));
    return Promise.reject(response.data);
  },
  async (error: any) => {

    // 非 2xx 状态码处理 401、403、500 等
    const { config, response } = error;
    if (response) {
      const { code, message } = response.data;
      if (code === ResultEnum.ACCESS_TOKEN_INVALID) {
        // Token 过期，刷新 Token
        return handleTokenRefresh(config);
      } else if (code === ResultEnum.REFRESH_TOKEN_INVALID) {
        return Promise.reject(new Error(message || "Error"));
      } else {
        ElMessage.error(message || "系统出错");
      }
    }
    return Promise.reject(error.message);
  }
);

export default service;

// 刷新 Token 的锁
let isRefreshing = false;
// 因 Token 过期导致失败的请求队列
let requestsQueue: Array<() => void> = [];

// 刷新 Token 处理
async function handleTokenRefresh(config: InternalAxiosRequestConfig) {
  return new Promise((resolve) => {
    const requestCallback = () => {
      config.headers.Authorization = getToken();
      resolve(service(config));
    };

    requestsQueue.push(requestCallback);

    if (!isRefreshing) {
      isRefreshing = true;

      // 刷新 Token
      useUserStoreHook()
        .refreshToken()
        .then(() => {
          // Token 刷新成功，执行请求队列
          requestsQueue.forEach((callback) => callback());
          requestsQueue = [];
        })
        .catch((error) => {
          console.log("handleTokenRefresh error", error);
          // Token 刷新失败，清除用户数据并跳转到登录
          ElNotification({
            title: "提示",
            message: "您的会话已过期，请重新登录",
            type: "info",
          });
          useUserStoreHook()
            .clearUserData()
            .then(() => {
              router.push("/login");
            });
        })
        .finally(() => {
          isRefreshing = false;
        });
    }
  });
}
