import Vue from "vue";
import axios, { AxiosRequestConfig } from "axios";
import VueAxios from "vue-axios";
import { MethodType } from "@/constants/enum/general/method-type.enum";
import { HeaderType } from "@/constants/enum/general/header-type.enum";
import { statusCode } from "@/constants/enum/general/status-code.enum";
import { tokenStore } from "@/stores/index";
import { NativeUI } from '@/public/ts/NativeUI';
import SMUtil from '@/public/ts/SMEncryt';
import { Code } from "@/constants/enum/general/code.enum";
import router from "@/router";
// import emUtil from '../js/em.util';

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);
//http request 拦截器
    Vue.axios.interceptors.request.use(
      config => {
        config.headers['Access-Control-Allow-Origin'] = '*';

        if(!config.headers['Content-Type']){
          config.headers['Content-Type'] = 'application/json; charset=utf-8';
        }
        const token = sessionStorage.getItem('accessToken');
        if (token && token != '') {
          config.headers.Authorization = 'bearer ' + token;
        }
        return Promise.resolve(config);
      },
      error => {
        console.error(error);
        return Promise.reject(error);
      }
    );

    const requestConfig: any = this.createBasicHeaders();
    Object.keys(requestConfig.headers).forEach(function (key) {
      Vue.axios.defaults.headers.common[key] = requestConfig.headers[key];
    });
    Vue.axios.interceptors.request.use(
      (config) => {
        // Do something before request is sent
        // if (this.verificationToken(config)) {
        //   return Promise.resolve(config);
        // } else {
        //   return oauthService.refreshToken().then((response: RestfulResponse) => {
        //     if (response) {
        //       config.headers.Authorization = "bearer " + tokenStore.token?.access_token;
        //       config.headers["user-identity"] = "bearer " + tokenStore.token?.jti;
        //       return config;
        //     } else {
        //       return oauthService.logOut().then();
        //     }
        //   });
        // }
        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: {
        Authorization: "bearer " + tokenStore.token?.access_token,
        "user-identity": tokenStore.token?.jti,
        "Content-Type": "application/json",
        Accept: "application/json",
      },
    };
  }

  /**
   * @description: 创建上传认证消息头
   * @author ChenRui
   * @date 2021/4/6 11:17
   */
  createFileUploadAuthorizationHeader() {
    return {
      headers: {
        Accept: "application/json",
        Authorization: "bearer " + tokenStore.token?.access_token,
        "user-identity": tokenStore.token?.jti,
        "Content-type": "application/x-www-form-urlencoded"
      },
    };
  }

  /**
   * @description: 创建认证下载消息头
   * @author ChenRui
   * @date 2020/8/28 15:18
   */
  createFileDownloadAuthorizationHeader() {
    return {
      headers: {
        "Content-Type": "application/json",
        Authorization: "bearer " + tokenStore.token?.access_token,
        "user-identity": tokenStore.token?.jti,
      },
      responseType: "blob",
    };
  }
  /**
   * @param headerType
   * @param headerConfig
   */
  getRequestConfig(headerType: any, requestConfig: any) {
    requestConfig = requestConfig || {};
    let requestConfigBase = {};
    switch (headerType) {
      case HeaderType.BASE.code:
        requestConfigBase = this.createBasicHeaders();
        break;
      case HeaderType.AUTH.code:
        requestConfigBase = this.createAuthHeaders();
        break;
      case HeaderType.UPLOAD_AUTH.code:
        requestConfigBase = this.createFileUploadAuthorizationHeader();
        break;
      case HeaderType.DOWNLOAD_AUTH.code:
        requestConfigBase = this.createFileDownloadAuthorizationHeader();
        break;
    }
    Object.keys(requestConfig).forEach((value: string, index: number, array: string[]) => {
      requestConfigBase[value] = requestConfig[value];
    });
    return requestConfigBase;
  }
  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.createBusCodeHandler(query)).catch(this.createErrorHandler());
  }

  post(path: string, params: any, query: Query | undefined, requestConfig: AxiosRequestConfig): any {

    path = query != null ? this.urlQueryConvert(path, query) : path;
    console.log("服务调用--" + path);

    return Vue.axios.post(`${path}`, params, requestConfig).then(this.createBusCodeHandler(query)).catch(this.createErrorHandler());


  }
  /**
   * POST请求 文件上传
   * @param path
   * @param params
   * @param requestConfig
   * @returns
   */
  uploadFile(path: string, params: any, requestConfig: any) {
    return Vue.axios.post(`${path}`, params, requestConfig).then(this.createBusCodeHandler(params)).catch(this.createErrorHandler());
  }
  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.createBusCodeHandler()).catch(this.createErrorHandler());
  }

  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.createBusCodeHandler()).catch(this.createErrorHandler());
  }

  /**
   * @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 {
    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:
            requestConfig = this.createFileUploadAuthorizationHeader();
            break;
          case HeaderType.DOWNLOAD_AUTH.code:
            requestConfig = this.createFileDownloadAuthorizationHeader();
            break;
        }
      } else {
        let requestConfigBase: any = {};
        switch (api.header) {
          case HeaderType.BASE.code:
            requestConfigBase = this.createBasicHeaders();
            break;
          case HeaderType.AUTH.code:
            requestConfigBase = this.createAuthHeaders();
            break;
          case HeaderType.UPLOAD_AUTH.code:
            requestConfigBase = this.createFileUploadAuthorizationHeader();
            break;
          case HeaderType.DOWNLOAD_AUTH.code:
            requestConfigBase = this.createFileDownloadAuthorizationHeader();
            break;
        }
        Object.keys(requestConfig).forEach((value, index, array) => {
          requestConfigBase[value] = requestConfig[value];
        });
        requestConfig = requestConfigBase;
      }
      switch (api.method) {
        case MethodType.GET.code:
          return this.get(api.url, query, requestConfig);
          break;
        case MethodType.PUT.code:
          return this.put(api.url, params, query, requestConfig);
          break;
        case MethodType.POST.code:
          return this.post(api.url, params, query, requestConfig);
          break;
        case MethodType.DELETE.code:
          return this.delete(api.url, query, requestConfig);
          break;
      }
    }
  }

  /**
   * 服务返回统一解密处理
   */
  createBusCodeHandler(params?: any) {
    return function(response: any) {
      
      if (response.status === 200) {
        let data = response.data;
        
        console.log("返回统一解密处理",params)
        if (params.tc === 'MCEP') {
          let encryData = data.data || {};
          console.log('返回原数据:', data);
          //移动后台
          if (typeof encryData != 'object') {
            encryData = JSON.parse(encryData);
          }
          
          // //三方数据 
          // encryData.sm4key ? (data.data = SMUtil.decodeData(encryData)) : data;
          // if (data.data && typeof data.data != 'object') {
          //   if (data.data.indexOf('{') > -1) {
          //     data.data = JSON.parse(data.data);
          //   }
          // }
          if (['local', 'production'].indexOf(process.env.NODE_ENV) == -1) {
             }
          console.log('返回数据:', data);
         
          if (data.code == '40902') {
            //token 失效,退出登录
            NativeUI.confirm('', "登录超时,请退出重新登录").then(() => {
              // emUtil.closeWindow();
              // 清空数据并回到登录页面
              sessionStorage.setItem("branchNo", "");
              sessionStorage.setItem("branchNo", "");
              router.push({path: "/login"}).then();
            });
          } else {
            return data;
          }
        } else {
          //三方数据
          if (data.code == '40902') {
            //token 失效,退出登录
            NativeUI.confirm("", "登录超时,请退出重新登录").then(() => {
              // emUtil.closeWindow();
              // 清空数据并回到登录页面
              sessionStorage.setItem("branchNo", "");
              sessionStorage.setItem("branchNo", "");
              router.push({path: "/login"}).then();
            });
          } else if (data.code == 1) {
            console.log(data);
            //成功
           // data = data.data;
          //  debugger
            if (typeof data != 'object') data = JSON.parse(data);
            data = data.sm4key ? SMUtil.decodeData(data) : data;
            if (typeof data != 'object') {
              if (data.indexOf('{') > -1) {
                data = JSON.parse(data);
              }
            }
            // if (['local', 'production'].indexOf(process.env.NODE_ENV) == -1) {
            console.log('**返回数据**', params.tc, data);
            // }
            return data;
          } else if (data.code == -1) {
            NativeUI.toast(data.msg);
            return data;
          } else {
            NativeUI.toast(data.msg);
            return data;
          }
        }
      }
      return response;
    };
  }

  /**
   * @description: 异常处理器
   * @author ChenRui
   * @date 2020/8/28 15:19
   */
  createErrorHandler() {
    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);
        return {
          code: Code.FAIL.code,
          msg: error.response?.data?.msg || "网络连接异常,稍后请重试或联系管理员",
        };
      } else if (error.request) {
        console.log(error.request);
        return {
          code: Code.FAIL.code,
          msg: error.request?.data?.msg || "网络连接异常,稍后请重试或联系管理员",
        };
      } else {
        // Something happened in setting up the request that triggered an Error
        console.log("Error", error.message);
        return {
          code: Code.FAIL.code,
          msg: "未知异常,稍后请重试或联系管理员",
        };
      }
    };
  }

  /**
   * @description: 校验令牌
   * @author ChenRui
   * @date 2021/8/11 15:02
   */
  verificationToken(config: AxiosRequestConfig) {
    if (config.headers != null && config.headers.Authorization != null && tokenStore.token != null) {
      // return oauthService.isTokenExpiration;
    }
    return true;
  }

  /**
   * @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格式转表单格式

   * @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;