/*
 * @Author: 赵伟
 * @Date: 2024-03-25 13:52:54
 * @Description: 网络请求配置，详情请参考 https://umijs.org/docs/max/request
 */
import type {
  AxiosError,
  AxiosRequestConfig,
  AxiosResponse,
  RequestConfig,
  RequestError,
  RequestOptions,
} from '@umijs/max';
import { message } from 'antd';
import { clearSessionToken, getAccessToken } from './access';
import { setRemoteMenu } from './services/session';
import Loading from './utils/loading';
import { gotoLoginPage } from './utils/ui';

// [antd: Notification] You are calling notice in render which will break in React 18 concurrent mode. Please trigger in effect instead.
const popupError = (error: string, skipErrorHandler: boolean | undefined = false) => {
  if (!skipErrorHandler) {
    // 直接调用 message.error 有时候不弹出来
    setTimeout(() => {
      message.error(error);
    }, 100);
  }
};

/**
 * Umi Max 网络请求配置
 * @doc https://umijs.org/docs/max/request#配置
 */
export const requestConfig: RequestConfig = {
  timeout: 120 * 1000,
  requestInterceptors: [
    (url: string, options: AxiosRequestConfig) => {
      const headers = options.headers ?? {};
      const authHeader = headers['Authorization'];
      const isToken = headers['isToken'];
      const skipLoading = (options as RequestOptions)?.skipLoading;
      if (!authHeader && isToken !== false) {
        const accessToken = getAccessToken();
        if (accessToken) {
          headers['Authorization'] = `Bearer ${accessToken}`;
        }
      }
      if (!skipLoading) {
        Loading.show();
      }
      return { url, options };
    },
  ],
  responseInterceptors: [
    [
      async (response: AxiosResponse) => {
        const { status, data, config } = response || {};
        const options = config as RequestOptions;
        const skipErrorHandler = options?.skipErrorHandler;
        const skipLoading = options?.skipLoading;
        const skipValidating = options?.skipValidating;
        if (!skipLoading) {
          Loading.hide();
        }
        if (status >= 200 && status < 300) {
          // 无内容或者无需验证
          if (status === 204 || skipValidating) {
            return response;
          }

          if (data && data.code === 200) {
            return response;
          }

          // Blob 数据
          if (data && data instanceof Blob && data.size > 0) {
            // 下载文件失败时，返回的是 JSON 数据，格式为：{code: 500, msg: "xxx"}
            if (data.type === 'application/json') {
              try {
                const text = await data.text();
                const json = JSON.parse(text);

                if (json.code === 500) {
                  popupError(json.msg || '请求失败', skipErrorHandler);
                  return Promise.reject(json);
                }
              } catch (error) {
                console.error('JSON 解析失败', error);
              }
            }
            return response;
          }

          // Token 失效
          if (data && data.code === 401) {
            clearSessionToken();
            setRemoteMenu(null);
            gotoLoginPage(false);
            popupError('请重新登录');
            return Promise.reject(response);
          }

          popupError(data?.msg ?? '请求失败', skipErrorHandler);
          return Promise.reject(response);
        } else {
          popupError('请求失败', skipErrorHandler);
          return Promise.reject(response);
        }
      },
      (error: RequestError) => {
        const options = (error as AxiosError).config as RequestOptions;
        const skipErrorHandler = options?.skipErrorHandler;
        const skipLoading = options?.skipLoading;
        if (!skipLoading) {
          Loading.hide();
        }
        popupError(error.message ?? '请求失败', skipErrorHandler);
        return Promise.reject(error);
      },
    ],
  ],
};
