import axios from 'axios';
import { MessagePlugin as Message } from 'tdesign-vue-next';
import { download, clear } from '@/utils/tool';
import { get, isEmpty } from 'lodash';
import qs from 'qs';
// import { h } from 'vue';
import { LoadingPlugin } from 'tdesign-vue-next';
import { getAuthorization, getMD5 } from './crypto';
import router from '@/router';
import { initSyncTime, fetchTime } from './syncServerTime';
import { cookie } from '@/utils/tool';

function getDeviceId() {
  let deviceId = cookie.get('deviceId');
  if (deviceId) return deviceId;

  if (!deviceId) {
    deviceId = getMD5(Math.random() + '-' + Date.now());
    cookie.set('deviceId', deviceId);
    return deviceId;
  }
}

function setAuth(config) {
  let userSession = sessionStorage.getItem('user');
  if (userSession && !config.noAuth) {
    let user = JSON.parse(userSession).user;
    const timestamp = fetchTime();
    const authorization = getAuthorization(
      {
        method: config.method,
        uri: config.url.split('?')[0].trim(),
        timestamp,
        sessionId: user.sessionId,
        token: user.accessToken,
      },
      'token'
    );
    config.headers['Authorization'] = authorization;
    config.headers['time'] = timestamp;
  }
}

function createService() {
  // 创建一个 axios 实例
  const service = axios.create();

  // HTTP request 拦截器
  service.interceptors.request.use(
    (config) => {
      setAuth(config);
      if (config.loading) {
        LoadingPlugin(true);
      }
      if (config.download) {
        config.responseType ??= 'blob';
      }
      return config;
    },
    (error) => {
      // 失败
      return Promise.reject(error);
    }
  );
  const rejectWhiteList = ['/api/admin/common/file/preview/app'];
  // HTTP response 拦截器
  service.interceptors.response.use(
    (response) => {
      initSyncTime(new Date(response.headers.date).getTime());

      if (response.config.loading) {
        LoadingPlugin(false);
      }
      // 以下代码看后端是否有统一在接口里增加外层code的规范
      if (response.data.code && response.data.code !== 200) {
        Message.error({
          content: response.data.message,
          closeBtn: true,
          // icon: () => h(IconFaceFrownFill),
        });
      }
      if (response.config.download && response.config.responseType === 'blob') {
        download(response);
      }
      return response.data?.data;
    },
    (error) => {
      if (error.response) {
        initSyncTime(new Date(error.response.headers.date).getTime());
      }
      if (error.config?.loading) {
        LoadingPlugin(false);
      }
      const err = (text) => {
        !rejectWhiteList.includes(error.config?.url) &&
          Message.error({
            closeBtn: true,
            content:
              (error?.response?.data?.message?.includes('权限')
                ? error?.config?.url + ' '
                : '') +
              (error.response &&
              error.response.data &&
              error.response.data.message
                ? error.response.data.message
                : text),
          });
      };
      if (error.response) {
        switch (error.response.status) {
          case 404:
            err(`服务器资源不存在`);
            break;
          case 500:
            err(`服务器内部错误`);
            break;
          case 401:
            if (
              error.response?.data?.message.includes('登录') ||
              error.response?.data?.message.includes('token')
            ) {
              Message.error('登录状态已过期');
              router.replace({ name: 'Login' });
            } else {
              err('登录状态已过期或没有权限');
            }
            break;
          case 403:
            err(`没有权限访问该资源`);
            break;
          default:
            err(JSON.stringify(error?.response || '未知错误'));
        }
      } else {
        err('请求超时，服务器无响应！');
      }
      return Promise.reject(
        error.response && error.response.data ? error.response.data : null
      );
    }
  );
  return service;
}

/**
 * @description 创建请求方法
 * @param {Object} service axios 实例
 */
function createRequest(service) {
  return function (config) {
    const env = import.meta.env;
    let headers = {
      'platform': 'WEB',
      'deviceId': getDeviceId(),
      ...(config.headers || {}),
      'Content-Type': get(
        config,
        'headers.Content-Type',
        'application/json;charset=UTF-8'
      ),
    };
    const configDefault = {
      method: 'post',
      timeout: 120000,
      baseURL: env.VITE_HTTP_PROXY === 'Y' ? '' : env.VITE_APP_BASE_URL,
      data: {},
    };
    const option = Object.assign(configDefault, config, { headers: headers });

    return service(option);
  };
}

export function paramsSerializer(params) {
  return qs.stringify(params);
}

// 用于真实网络请求的实例和请求方法
export const service = createService();
export const request = createRequest(service);
