import defaultFetch from "isomorphic-fetch";
import { FORM_DATA_TYPE, URL_HTTP_REG } from "./constant";
import globalConfig from "./globalConfig";
import { FastOptions, FetchOptions, GlobalConfig } from "./@types/";
/**
 * 默认加上请求方法，第二个参数约定为请求参数
 */
export const fastFetchFactory = (fetch: any, opts: FastOptions) => (
  api: string,
  params: any = {},
  ...args
) =>
  fetch(
    api,
    {
      body: params || {},
      ...opts
    },
    ...args
  );

/**
 * 默认的配置项
 */

const createDefaultConfig = (): GlobalConfig => globalConfig.get("config");

export const fetchWebapi = async (
  api: string,
  opts: FetchOptions = {},
  getConfig = createDefaultConfig
) => {
  /**
   * getConfig 必须在运行时调用，才能保证获取的配置是最新的
   * @returns interceptor
   * @returns prefix
   * @returns fetchOption
   */

  const { interceptor, prefix, fetchOption, responseHandle } = getConfig();
  const {
    requestInterceptor,
    responseInterceptor,
    errorInterceptor
  } = interceptor;

  let url, options, startTime, endTime;

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

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

    url = request.api;
    options = request.options;

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

    const fetch = options.fetch || defaultFetch;

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

    startTime = Date.now();

    const response = await fetch(url, options);

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

    endTime = Date.now();

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

    const res = await responseHandle({
      response,
      options: {
        startTime,
        endTime
      }
    });

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

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