import Vue from "vue";
import axios, { AxiosRequestConfig } from "axios";
import VueAxios from "vue-axios";
import { MethodType } from "@/constants/enum/method-type.enum";
import { HeaderType } from "@/constants/enum/header-type.enum";
import { tokenStore } from "@dhccmobile/etbc-auth-api";
import { CoreConfig } from "@/model";

interface Query {
  [key: string]: any;
}
/**
 * @description: REST请求服务
 * @author ChenRui
 * @date 2020/7/29 18:45
 */
class ApiService {
  /**
   * @description: 初始化
   * @author ChenRui
   * @date 2020/8/29 23:36
   */
  init() {
    Vue.use(VueAxios, axios);

    const headers = this.createBasicHeaders();
    Object.keys(headers).forEach(function(key) {
      Vue.axios.defaults.headers.common[key] = headers[key];
    });

    Vue.axios.interceptors.request.use(
      config => {
        // Do something before request is sent
        /*if (this.verificationToken(config)) {
          return Promise.resolve(config);
        } else {
          return authService.refreshToken().then((response: RestfulResponse) => {
            if (response) {
              config.headers.Authorization = "bearer " + tokenStore.getAccessToken();
              return config;
            } else {
              authService.logOut().then((response: RestfulResponse) => {
                if (process.env.VUE_APP_ENABLE_REGISTER === EnableType.ON.code) {
                  routerService.push(qiankunService.globalState.loginPage);
                } else {
                  Vue.prototype.$router.push({ path: "/no-access" });
                }
              });
              return Promise.reject("刷新失败");
            }
          });
        }*/
        return Promise.resolve(config);
      },
      error => {
        // Do something with request error
        console.log("Do something with request error");
        return Promise.reject(error);
      }
    );
  }

  /**
   * @description:  创建基础消息头
   * @author ChenRui
   * @date 2020/8/28 15:18
   */
  createBasicHeaders(): any {
    return {
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      }
    };
  }

  /**
   * @description: 创建认证消息头
   * @author ChenRui
   * @date 2020/8/28 15:18
   */
  createAuthHeaders(): any {
    return {
      headers: {
        token: tokenStore.token?.accessToken,
        "Content-Type": "application/json",
        Accept: "application/json",
        accessToken: tokenStore.adminToken
      }
    };
  }

  /**
   * @description: 创建上传认证消息头
   * @author ChenRui
   * @date 2021/4/6 11:17
   */
  createFileUploadAuthorizationHeader() {
    return {
      headers: {
        Accept: "application/json",
        token: tokenStore.token?.accessToken,
        accessToken: tokenStore.adminToken
      }
    };
  }

  /**
   * @description: 创建认证下载消息头
   * @author ChenRui
   * @date 2020/8/28 15:18
   */
  createFileDownloadAuthorizationHeader() {
    return {
      headers: {
        "Content-Type": "application/json",
        token: tokenStore.token?.accessToken,
        accessToken: tokenStore.adminToken
      },
      responseType: "blob"
    };
  }

  get(path: string, query: Query | undefined, requestConfig: AxiosRequestConfig): any {
    path = query != null ? this.urlQueryConvert(path, query) : path;
    return Vue.axios
      .get(`${path}`, requestConfig)
      .then(this.createBusCodeHander())
      .catch(this.createErrorHander());
  }

  post(path: string, params: any, query: Query | undefined, requestConfig: AxiosRequestConfig): any {
    path = query != null ? this.urlQueryConvert(path, query) : path;
    return Vue.axios
      .post(`${path}`, params, requestConfig)
      .then(this.createBusCodeHander())
      .catch(this.createErrorHander());
  }

  put(path: string, params: any, query: Query | undefined, requestConfig: AxiosRequestConfig): any {
    path = query != null ? this.urlQueryConvert(path, query) : path;
    return Vue.axios
      .put(`${path}`, params, requestConfig)
      .then(this.createBusCodeHander())
      .catch(this.createErrorHander());
  }

  delete(path: string, query: Query | undefined, requestConfig: AxiosRequestConfig): any {
    path = query != null ? this.urlQueryConvert(path, query) : path;
    return Vue.axios
      .delete(path, requestConfig)
      .then(this.createBusCodeHander())
      .catch(this.createErrorHander());
  }
  /**
   * @description: 获取全局配置
   * @author ChenRui
   * @date 2020/12/17 16:16
   */
  get coreConfig(): Partial<CoreConfig> {
    if (Vue.prototype.$apData != null) {
      return Vue.prototype.$apData;
    }
    return {};
  }
  /**
   * @description: 通用请求函数
   * @author ChenRui
   * @date 2020/8/28 15:19
   * @param api               调用接口的对象
   * @param query             问号？后参数
   * @param params            post、put、delete参数 非必须
   * @param requestConfig     请求配置，如果上传文件、form提交等配置 非必须
   */
  general(api: any, query: Query | undefined, params?: any | undefined, requestConfig?: AxiosRequestConfig | any): any {
    let url = this.coreConfig ? (this.coreConfig.processServiceUrl || "") + (this.coreConfig.apiPrefix || "") + api.url : "";
    if (!!api.url && !!api.method) {
      if (requestConfig == null) {
        switch (api.header) {
          case HeaderType.BASE.code:
            requestConfig = this.createBasicHeaders();
            break;
          case HeaderType.AUTH.code:
            requestConfig = this.createAuthHeaders();
            break;
          case HeaderType.UPLOAD_AUTH.code:
            url = this.coreConfig ? (this.coreConfig.fileApi || "") + api.url : "";
            requestConfig = this.createFileUploadAuthorizationHeader();
            break;
          case HeaderType.DOWNLOAD_AUTH.code:
            url = this.coreConfig ? (this.coreConfig.fileApi || "") + api.url : "";
            requestConfig = this.createFileDownloadAuthorizationHeader();
            break;
        }
      }
      switch (api.method) {
        case MethodType.GET.code:
          return this.get(url, query, requestConfig);
          break;
        case MethodType.PUT.code:
          return this.put(url, params, query, requestConfig);
          break;
        case MethodType.POST.code:
          return this.post(url, params, query, requestConfig);
          break;
        case MethodType.DELETE.code:
          return this.delete(url, query, requestConfig);
          break;
      }
    }
  }

  /**
   * @description: 错误码处理器
   * @author ChenRui
   * @date 2020/8/28 15:19
   */
  createBusCodeHander() {
    return function(response: any) {
      if (response.status === 200) {
        return response.data;
      }
      return response;
    };
  }

  /**
   * @description: 异常处理器
   * @author ChenRui
   * @date 2020/8/28 15:19
   */
  createErrorHander() {
    return function(error: any) {
      if (error.response) {
        // The request was made and the server responded with a status code
        // that falls out of the range of 2xx
        /*console.log(error.response.data);*/
        console.log(error.response);
        return {
          code: 0,
          msg: error.response?.data?.msg || "网络连接异常，稍后请重试或联系管理员"
        };
      } else if (error.request) {
        console.log(error.request);
        return {
          code: 0,
          msg: error.request?.data?.msg || "网络连接异常，稍后请重试或联系管理员"
        };
      } else {
        // Something happened in setting up the request that triggered an Error
        console.log("Error", error.message);
        return {
          code: 0,
          msg: "未知异常，稍后请重试或联系管理员"
        };
      }
    };
  }

  /**
   * @description: 日期格式化
   * @author ChenRui
   * @date 2020/8/28 15:20
   */
  formatDate(date: any) {
    date = new Date(date);
    const YY = date.getFullYear() + "-";
    const MM = (date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1) + "-";
    const DD = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
    const hh = (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":";
    const mm = (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":";
    const ss = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
    return YY + MM + DD + " " + hh + mm + ss;
  }

  /**
   * @description: json格式转表单格式
   * @author ChenRui
   * @date 2020/8/28 15:20
   */
  jsonToFormData(params: any) {
    if (params != null) {
      const formData = new FormData();
      Object.keys(params).forEach(key => {
        formData.append(key, params[key]);
      });
      return formData;
    }
  }

  /**
   * @description: url请求参数组装
   * @author ChenRui
   * @date 2020/8/28 15:21
   */
  urlQueryConvert(url: string, query: Query) {
    let connectiveSymbol = "";
    if (url.indexOf("?") !== -1) {
      connectiveSymbol = "&";
    } else {
      connectiveSymbol = "?";
    }
    if (query) {
      Object.keys(query).forEach((key, idx) => {
        const val = query[key];
        if (idx === 0) {
          if (val != null && val !== "null" && val !== "undefined") {
            url += connectiveSymbol + key + "=" + val;
          } else {
            url += connectiveSymbol + key + "=";
          }
        } else {
          if (val != null && val !== "null" && val !== "undefined") {
            url += "&" + key + "=" + val;
          } else {
            url += "&" + key + "=";
          }
        }
      });
    }
    return url;
  }
}
const apiService = new ApiService();
export default apiService;
