import fetch from "isomorphic-fetch";
import { FORM_DATA_TYPE } from "./constant";
import globalConfig from "./globalConfig";
export interface FetchOptions extends RequestInit {
  body: any;
  fetch?: any;
}

export interface Interceptor {
  requestInterceptor: ({
    api: string,
    options: FetchOptions
  }) => {
    url: string;
    options: FetchOptions;
  } | void;
  responseInterceptor: ({
    res: Response,
    options: FetchDate
  }) => { res: Response; options: ResponseOptions } | void;
  errorInterceptor: ({
    error: Error,
    options: ErrorOptions
  }) => { error: Error; options: ErrorOptions } | void;
}

export interface ErrorOptions {
  type: string;
  url: string;
  args: {
    options: FetchOptions;
    startTime: number;
    endTime: number;
  };
}

export interface ResponseOptions {
  startTime: number;
  endTime: number;
}

// 请求方法
async function defaultFetch(
  request: RequestInfo,
  options?: FetchOptions
): Promise<Response> {
  const json = await fetch(request, options);
  return json;
}

export const fetchWebapi = async (api: string, opts: FetchOptions) => {
  let url, options, startTime, endTime;

  const interceptor = globalConfig.get("interceptor");
  const prefix = globalConfig.get("prefix");
  const fetchOption = globalConfig.get("fetchOption");
  const {
    requestInterceptor,
    responseInterceptor,
    errorInterceptor
  } = interceptor;

  try {
    /**
     * 请求拦截器
     */

    const request = requestInterceptor({
      api: `${prefix}${api}`,
      options: Object.assign({}, fetchOption, opts)
    });

    url = request.url || "";
    options = request.options || {};

    /**
     * 如果没有，默认使用fetch
     * 要求必须是返回promise的方法
     */

    const fetch = options.fetch || defaultFetch;

    /**
     * 打印请求开始时间
     */

    startTime = Date.now();

    const res = await fetch(url, options);

    /**
     * 打印请求结束时间
     */

    endTime = Date.now();

    /**
     * 返回响应拦截器的值
     *
     * @example
     * const responseInterceptor  =  (res)=>res.clone().json()
     *
     */

    return responseInterceptor({
      res,
      options: {
        startTime,
        endTime
      }
    });
  } catch (error) {
    errorInterceptor({
      error,
      options: {
        type: "fetch",
        url,
        args: {
          options,
          startTime,
          endTime
        }
      }
    });
  }
};

export interface FastOptions {
  method: string;
  headersType?: string;
}

const fastFetch = (opts: FastOptions) => (api: string, params: any = {}) =>
  fetchWebapi(api, {
    body: params || {},
    ...opts
  });

// 快捷方法
fetchWebapi.get = fastFetch({ method: "GET" });
fetchWebapi.post = fastFetch({ method: "POST" });
fetchWebapi.put = fastFetch({ method: "PUT" });
fetchWebapi.delete = fastFetch({ method: "DELETE" });
fetchWebapi.upload = fastFetch({
  method: "POST",
  headersType: FORM_DATA_TYPE
});
