import { useAccessStore, useUserStore } from '@vben/stores';

import { message as Message } from 'ant-design-vue';

import { postApiAppAccountRefreshToken } from '#/api-client';
import { $t } from '#/locales';
import { antdLocale } from '#/locales/index';
import { useAuthStore } from '#/store';

import { client } from '../api-client/services.gen';

client.setConfig({
  baseURL: import.meta.env.DEV
    ? '/proxy/'
    : import.meta.env.VITE_APP_API_ADDRESS,
  timeout: 1000 * 60,
  responseType: 'json',
  throwOnError: true,
});
// 是否正在刷新token
let isRefreshing = false;
// 刷新token队列
let refreshTokenQueue: ((token: string) => void)[] = [];
client.instance.interceptors.request.use((request) => {
  // 全局拦截请求发送前提交的参数
  const userStore = useUserStore();
  const accessStore = useAccessStore();
  const token = accessStore.getAccessToken();
  // 设置请求头
  if (request.headers) {
    request.headers.__tenant = userStore.tenant?.tenantId;
    // todo vben5 没有提供统一获取当前语言的方式
    request.headers['accept-language'] = antdLocale.value.locale;
  }

  // 如果token过期，则跳转到登录页面
  if (
    request.url !== undefined &&
    request.url.includes('/api/app/account/login')
  ) {
    return request;
  }

  // 设置请求头
  if (request.headers) {
    request.headers.Authorization = `Bearer ${token}`;
  }

  return request;
});

client.instance.interceptors.response.use(
  (response) => {
    return Promise.resolve(response);
  },
  async (error) => {
    let message = error.message;
    if (message === 'Network Error') {
      message = $t('common.mesage500');
    } else if (message.includes('timeout')) {
      message = $t('common.timeOut');
    } else
      switch (error.status) {
        case 400: {
          message = error.response.data.error?.validationErrors[0].message;
          break;
        }
        case 401: {
          message = $t('common.mesage401');
          const { config } = error;
          const originalRequest = config;
          if (isRefreshing) {
            return new Promise((resolve) => {
              refreshTokenQueue.push((token) => {
                originalRequest.headers.Authorization = `Bearer ${token}`;
                resolve(client.request(originalRequest));
              });
            });
          } else {
            isRefreshing = true;
            try {
              const newToken = await refreshTokenAsync();
              // 处理队列中的请求
              refreshTokenQueue.forEach((callback) => callback(newToken));
              // 清空队列
              refreshTokenQueue = [];
              return client.request(originalRequest);
            } catch (refreshError) {
              // 如果刷新 token 失败，处理错误（如强制登出或跳转登录页面）
              message = $t('common.mesage401');
              refreshTokenQueue = [];
              const authStore = useAuthStore();
              authStore.logout();
              console.error(refreshError);
            } finally {
              isRefreshing = false;
            }
          }
          break;
        }
        case 403: {
          message = $t('common.mesage403');
          break;
        }
        case 500: {
          message = error.response.data.error?.message;
          break;
        }
        default: {
          if (message.includes('Request failed with status code')) {
            message = $t('common.mesage500');
          }
        }
      }
    Message.error(message);
    throw error;
  },
);

async function refreshTokenAsync(): Promise<string> {
  try {
    const userStore = useUserStore();
    const accessStore = useAccessStore();
    const refreshToken = accessStore.getRefreshToken();
    if (!refreshToken) return '';
    const res = await postApiAppAccountRefreshToken({
      body: {
        userId: userStore.userInfo?.id,
        refreshToken,
      },
    });
    if (res?.data?.success) {
      accessStore.setAccessToken(res.data.token as string);
      accessStore.setRefreshToken(res.data.refreshToken as string);
      return res.data.token as string;
    } else {
      throw new Error('get refreshToken error');
    }
  } catch {
    throw new Error($t('common.mesage401'));
  }
}
export default client;
