import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios';
import { toast } from 'sonner';
import { env } from './env';
import { getRefreshToken, setToken, setAccessToken, setRefreshToken, clearAuth } from './auth';
import { loginApi } from '../api/Login';

// 创建 axios 实例
const axiosInstance: AxiosInstance = axios.create({
  baseURL: env.baseUrl ? `${env.baseUrl}/admin-api` : '/admin-api',
  timeout: 30000, // 30秒超时
  headers: {
    'Content-Type': 'application/json',
  },
});

// 是否正在刷新token
let isRefreshing = false;
// 待重试的请求队列
let failedQueue: Array<{
  resolve: (value?: any) => void;
  reject: (reason?: any) => void;
}> = [];

// 处理队列中的请求
const processQueue = (error: any, token: string | null = null) => {
  failedQueue.forEach(prom => {
    if (error) {
      prom.reject(error);
    } else {
      prom.resolve(token);
    }
  });
  failedQueue = [];
};

// 统一的token刷新函数
const refreshTokenAndRetry = async (originalRequest: InternalAxiosRequestConfig & { _retry?: boolean }) => {
  // 如果是刷新token的请求失败，不退出登录，继续保留当前页面
  if (originalRequest.url?.includes('/refresh-token') || originalRequest._retry) {
    const errorMessage = 'Token刷新失败，请稍后重试';
    return Promise.reject(new Error(errorMessage));
  }

  // 如果正在刷新token，将请求加入队列
  if (isRefreshing) {
    return new Promise((resolve, reject) => {
      failedQueue.push({ resolve, reject });
    })
      .then((token) => {
        if (originalRequest.headers) {
          originalRequest.headers.Authorization = `Bearer ${token}`;
        }
        return axiosInstance(originalRequest);
      })
      .catch((err) => {
        return Promise.reject(err);
      });
  }

  // 尝试刷新token
  const refreshToken = getRefreshToken();
  if (!refreshToken) {
    const errorMessage = 'RefreshToken不存在，无法刷新';
    return Promise.reject(new Error(errorMessage));
  }

  isRefreshing = true;
  originalRequest._retry = true;

  try {
    const res: any = await loginApi.refreshToken(refreshToken);
    
    // 处理返回数据格式：{code: 0, data: {accessToken, refreshToken, ...}, msg: ""}
    let tokenData;
    if (res?.code === 0 && res?.data) {
      // 标准格式：{code: 0, data: {...}}
      tokenData = res.data;
    } else if (res?.data) {
      // 兼容格式：{data: {...}}
      tokenData = res.data;
    } else {
      // 直接是数据对象
      tokenData = res;
    }
    
    const newAccessToken = tokenData?.accessToken || tokenData?.token;
    const newRefreshToken = tokenData?.refreshToken;

    if (newAccessToken) {
      // 更新token
      setToken({ accessToken: newAccessToken, token: newAccessToken });
      setAccessToken(newAccessToken);
      if (newRefreshToken) {
        setRefreshToken(newRefreshToken);
      }

      // 更新请求头
      if (originalRequest.headers) {
        originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
      }

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

      // 重试原始请求
      return axiosInstance(originalRequest);
    } else {
      throw new Error('刷新token失败：未返回新token');
    }
  } catch (refreshError: any) {
    // 刷新失败，不清除认证信息，不跳转登录，继续保留当前页面
    const errorMessage = refreshError?.message || 'Token刷新失败，请稍后重试';
    processQueue(refreshError, null);
    return Promise.reject(new Error(errorMessage));
  } finally {
    isRefreshing = false;
  }
};

// 请求拦截器
axiosInstance.interceptors.request.use(
  (config) => {
    // 从 localStorage 获取 token
    const token = localStorage.getItem('token');
    if (token && config.headers) {
      config.headers.Authorization = `Bearer ${token}`;
    }

    // 添加租户信息（如果启用租户功能）
    const tenantEnable = env.tenantEnable;
    if (tenantEnable) {
      const tenantId = localStorage.getItem('tenantId');
      if (tenantId && config.headers) {
        // 使用 tenant-id 作为请求头名称（小写，带连字符）
        config.headers['tenant-id'] = tenantId;
      }
    }

    return config;
  },
  (error: AxiosError) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
axiosInstance.interceptors.response.use(
  (response: AxiosResponse) => {
    const { data, config } = response;

    // 如果是 blob 类型响应（文件下载），直接返回
    if (config.responseType === 'blob' || data instanceof Blob) {
      return data;
    }

    // 如果后端返回的数据格式是 { code, data, message }
    if (data.code !== undefined) {
      if (data.code === 200 || data.code === 0) {
        return data.data !== undefined ? data.data : data;
      } else if (data.code === 401) {
        // 业务错误码 401，表示未登录，需要处理 token 刷新或退出登录
        const originalRequest = config as InternalAxiosRequestConfig & { _retry?: boolean };
        return refreshTokenAndRetry(originalRequest);
      } else {
        // 其他业务错误 - 创建一个包含更多信息的错误对象
        const errorMessage = data.message || data.msg || '请求失败';
        const error = new Error(errorMessage) as any;
        error.response = {
          data: data,
          status: data.code,
        };
        error.config = config;
        
        // 如果 code 是 401，需要处理认证问题
        if (data.code === 401) {
          const originalRequest = config as InternalAxiosRequestConfig & { _retry?: boolean };
          return refreshTokenAndRetry(originalRequest);
        }
        
        // 不在这里显示 toast，让调用方决定是否显示
        // toast.error(errorMessage);
        return Promise.reject(error);
      }
    }

    // 直接返回数据
    return data;
  },
  (error: AxiosError) => {
    // 处理 HTTP 错误
    if (error.response) {
      const { status, data } = error.response;
      let errorMessage = '请求失败';

      switch (status) {
        case 401:
          // 获取原始请求配置
          const originalRequest = error.config as InternalAxiosRequestConfig & { _retry?: boolean };
          if (originalRequest) {
            return refreshTokenAndRetry(originalRequest);
          }
          errorMessage = '未授权，请重新登录';
          break;
        case 403:
          errorMessage = '拒绝访问';
          break;
        case 404:
          errorMessage = '请求的资源不存在';
          break;
        case 500:
          errorMessage = '服务器内部错误';
          break;
        case 502:
          errorMessage = '网关错误';
          break;
        case 503:
          errorMessage = '服务不可用';
          break;
        default:
          errorMessage = (data as any)?.message || `请求失败 (${status})`;
      }

      toast.error(errorMessage);
      return Promise.reject(new Error(errorMessage));
    } else if (error.request) {
      // 请求已发出但没有收到响应
      toast.error('网络错误，请检查网络连接');
      return Promise.reject(new Error('网络错误'));
    } else {
      // 其他错误
      toast.error(error.message || '请求失败');
      return Promise.reject(error);
    }
  }
);

// 包装 axiosInstance 为 request 对象，提供统一的 API 调用方式
// 这个对象用于兼容一些 API 文件中的调用方式
const request = {
  get: async (config: { url: string; params?: any; responseType?: string }) => {
    const { url, params, responseType } = config;
    return await axiosInstance.get(url, { params, responseType: responseType as any });
  },

  post: async (config: { url: string; data?: any }) => {
    const { url, data } = config;
    return await axiosInstance.post(url, data);
  },

  put: async (config: { url: string; data?: any }) => {
    const { url, data } = config;
    return await axiosInstance.put(url, data);
  },

  delete: async (config: { url: string; params?: any }) => {
    const { url, params } = config;
    return await axiosInstance.delete(url, { params });
  },

  download: async (config: { url: string; params?: any }) => {
    const { url, params } = config;
    return await axiosInstance.get(url, { params, responseType: 'blob' });
  },
};

// 导出 request 对象（用于兼容 config/axios.ts 的用法）
export { request };

// 默认导出 axiosInstance（保持向后兼容，很多 API 文件使用 import axiosInstance from '../utils/axios'）
export default axiosInstance;

