import axios from 'axios';
import type {
  InternalAxiosRequestConfig,
  AxiosRequestConfig,
  AxiosResponse,
} from 'axios';
import { Loading } from '@element-plus/icons-vue';
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus';
import type { MessageHandler } from 'element-plus';
import { initSyncTime, fetchTime } from '../utils/syncServerTime';
import { getAuthorization } from '../utils/crypto';
// import { DEVICE_ID, PLATFORM } from '../constants/app';
import { objTypeOf } from '../utils/utils';
import { useUserStore } from '../store';

axios.defaults.timeout = 60 * 1000;
axios.defaults.headers.post['Content-Type'] =
  'application/x-www-form-urlencoded';

let load: MessageHandler | null = null;
// 同一时间有多个请求时，会形成队列。在第一个请求创建loading，在最后一个响应关闭loading
const queue: Array<string | undefined> = [];
// 防止鉴权失效之后多次弹窗。
let unauthMsgBoxIsShow = false;

const modifyConfig = (config: AxiosRequestConfig): void => {
  const userStore = useUserStore();
  if (!config.headers) config.headers = {};

  if (userStore.accessToken) {
    // 新版鉴权
    const timestamp = fetchTime();
    const Authorization = getAuthorization(
      {
        token: userStore.accessToken,
        timestamp,
        account: userStore.loginName,
        uri: config.url?.split('?')[0] || '',
        method: config.method as string,
      },
      'token'
    );
    config.headers.Authorization = Authorization;
    config.headers.time = String(timestamp);
  }
  // config.headers.deviceId = DEVICE_ID;
  // config.headers.platform = PLATFORM;
  // config.headers.domain = window.location.origin;
};

axios.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 显示loading提示
    if (!queue.length) {
      load = ElMessage({
        customClass: 'el-message-loading',
        icon: Loading,
        message: '加载中...',
        duration: 0,
      });
    }
    queue.push(config.url);

    modifyConfig(config as AxiosRequestConfig);
    return config;
  },
  (error) => {
    // 关闭loading提示
    setTimeout(() => {
      queue.shift();
      if (!queue.length) load?.close();
    }, 100);

    ElMessage({
      type: 'error',
      message: error.message || '请求错误',
      duration: 5 * 1000,
    });
    return Promise.reject(error);
  }
);
// add response interceptors
axios.interceptors.response.use(
  (response: AxiosResponse) => {
    initSyncTime(new Date(response.headers.date).getTime());
    // 关闭loading提示
    setTimeout(() => {
      queue.shift();
      if (!queue.length) load?.close();
    }, 100);

    if (response.config.responseType === 'blob') return response;

    return response.data;
  },
  (error) => {
    console.log(error);

    // 关闭loading提示
    setTimeout(() => {
      queue.shift();
      if (!queue.length) load?.close();
    }, 100);

    // console.dir(error);

    if (!error.response) {
      let message = error.message || '无响应错误';
      if (message.indexOf('timeout') > -1) {
        message = '响应超时';
      }
      ElMessage({
        type: 'error',
        message,
        duration: 5 * 1000,
      });
      return Promise.reject(error);
    }

    const { response } = error;
    initSyncTime(new Date(response.headers.date).getTime());

    if (objTypeOf(response.data) === 'blob')
      return Promise.reject(error.response.data);

    const errorData = response.data;
    let message = errorData.message || '响应未知错误';
    const unauthStatus = [401, 403];

    if (!unauthStatus.includes(response.status)) {
      ElNotification.error({
        title: '错误提示',
        message,
        // closable: true, // Element Plus 默认 closable 为 true
      });
      return Promise.reject(error);
    }

    if (errorData.code === 401001 && message === '没有权限') {
      ElNotification.error({
        title: '错误提示',
        message,
        // closable: true, // Element Plus 默认 closable 为 true
      });
      return Promise.reject(error);
    }

    if (unauthMsgBoxIsShow) return Promise.reject(error);

    const exposeMsgs = ['系统授权信息已过期，请联系系统管理员激活!'];
    unauthMsgBoxIsShow = true;
    message = exposeMsgs.includes(message)
      ? message
      : '身份验证失效，请重新登录！';

    ElMessageBox.confirm(message, '重新登陆?', {
      confirmButtonText: '确定',
      showCancelButton: false,
      type: 'error',
      autofocus: false,
      closeOnClickModal: false,
      closeOnPressEscape: false,
      showClose: false,
    })
      .then(() => {
        unauthMsgBoxIsShow = false;
        const userStore = useUserStore();
        userStore.logout(false);
      })
      .catch(() => {
        // 用户点击了关闭按钮或者按了 ESC，理论上不会发生，因为 showClose 和 closeOnPressEscape 都是 false
        unauthMsgBoxIsShow = false; // 也需要重置状态
      });

    return Promise.reject(error);
  }
);
