import axios, { AxiosRequestConfig, Method } from "axios";
import { message } from "antd";
import { session } from "./session";
import { util } from "./util";
import _ from "lodash";

export type Option = {
  headers?: any;
  params?: any;
  unfilter?: boolean;
  responseType?: any;
  noRedirect?: any;
};

const globalOptions = {
  headers: {
    "Content-Type": "application/json",
    Accept: "application/json"
  }
};

const needLogin = (showMessage = true) => {
  if (showMessage) {
    message.error("请登陆后再进行操作");
  }
  session.destroy();
  // @ts-ignore
  window.location.href = `${util.getPublicPath()}#/passport/sign-in`;
};

const needAccess = () => {
  // @ts-ignore
  window.location.href = `${util.getPublicPath()}#/exception/403`;
};

const notfound = () => {
  // @ts-ignore
  window.location.href = `${util.getPublicPath()}#/exception/404`;
};

const gotError = () => {
  // @ts-ignore
  window.location.href = `${util.getPublicPath()}#/exception/500`;
};

class Request {
  private readonly baseURL: string;

  constructor(baseURL: string = "") {
    this.baseURL = baseURL;
  }

  get(url: string, options?: Option) {
    return this._request("get", url, null, options);
  }

  post(url: string, data?: any, options?: Option) {
    return this._request("post", url, data, options);
  }

  put(url: string, data?: any, options?: Option) {
    return this._request("put", url, data, options);
  }

  delete(url: string, options?: Option) {
    return this._request("delete", url, null, options);
  }

  setToken() {
    const token = session.getAccessToken();
    globalOptions.headers["Authorization"] = `Bearer ${token}`;
  }

  clearToken() {
    globalOptions.headers["Authorization"] = null;
    delete globalOptions.headers["Authorization"];
  }

  _request(method: Method, url: string, data: any, options: Option = {}): Promise<{ success: boolean; data?: any; page?: any; errorMsg?: any }> {
    if (
      /(?=\/api)\/api(\/pk|\/token\/login|\/idm-applications\/micro-frontend|\/system-parameter\/public|\/apps\/.+\/sign-in-page)/.test(
        url
      )
    ) {
      this.clearToken();
    } else {
      this.setToken();
    }
    const headers = Object.assign({}, globalOptions.headers, options.headers);
    const opt: AxiosRequestConfig = {
      baseURL: this.baseURL,
      withCredentials: true,
      method,
      url, //: config.apiHost + url,
      data,
      params: options.params || {},
      headers,
      responseType: options.responseType
    };
    return axios(opt)
      .then((res: any) => {
        if (res.status === 401 && !options.noRedirect) {
          needLogin();
          return {
            success: false
          };
        } else if (res.status === 403) {
          needAccess();
        } else if (res.status !== 200 && res.status !== 201 && res.status !== 204) {
          return {
            success: false,
            errorMsg: res.errorMsg
          };
        }
        const data = res.data;

        //如果数据是string类型，直接返回
        if (_.isString(data)) {
          return { success: true, data, page: { total: 0 } };
        }

        let total = _.get(res.headers, "x-total-count", 0);
        let page = { total: total ? parseInt(total, 10) : 0 };

        if (_.has(data, "errorCode")) {
          // 规范接口返回{errorCode, errorMsg, data}
          if (data.errorCode === 401 && !options.noRedirect) {
            needLogin();
            return {
              success: false,
              errorMsg: data.errorMsg
            };
          }
          if (data.errorCode === 403) {
            needAccess();
            return {
              success: false,
              errorMsg: data.errorMsg
            };
          }
          if (data.errorCode !== 0) {
            return {
              success: false,
              data: {},
              page: { total: 0 },
              errorMsg: data.errorMsg
            };
          }

          // 规范分页接口， 从返回数据中获取total构建page对象
          if (data.data && (_.has(data.data, "totalElements") || _.has(data.data, "total"))) {
            if (_.has(data.data, "totalElements")) {
              total = _.get(data.data, "totalElements", 0);
            } else {
              total = _.get(data.data, "total", 0);
            }
            page = {
              total: parseInt(total, 10)
            };

            return {
              success: true,
              page,
              data: _.get(data, "data.content", []),
              errorMsg: data.errorMsg
            };
          }

          return {
            success: true,
            data: _.get(data, "data", null),
            page,
            errorMsg: data.errorMsg
          };
        } else {
          // 兼容不规范接口
          if (data && _.isArray(data)) {
            page = {
              total: total ? parseInt(total, 10) : data ? data.length : 0
            };
          }

          return {
            success: true,
            data,
            page,
            errorMsg: data?.errMsg
          };
        }
      }).catch((err: any) => {
        const resp = err.response;
        let errorMsg = "系统错误";
        if (resp.status === 401) {
          if (/(?=\/api)\/api(\/token\/login)/.test(url)) {
            errorMsg = "用户名密码错误";
          } else {
            message.error("请登陆后再进行操作");
            errorMsg = "请登陆后再进行操作";
          }
          if (!options.noRedirect) {
            needLogin(false);
          }
        } else if (resp.status === 403) {
          errorMsg = "请登陆后再进行操作";
          needAccess();
        } else if (resp.status === 404) {
          // notfound();
          errorMsg = "资源未找到";
        } else if (resp.status === 500) {
          // gotError();
          errorMsg = "服务器内部错误";
          console.log(resp);
        }
        return {
          success: false,
          errorMsg
        };
      });
  }
}

export const request = new Request("");
export default request;
