import { DEFAULT_CONFIG } from "./constant";
import {
  invariant,
  isPlainObject,
  isString,
  isArray,
  isFunction,
  compose
} from "./utils";
import globalConfig from "./globalConfig";
import { fetchWebapi, Interceptor } from "./fetch";

export interface FetchConfig {
  prefix?: string;
  fetchOption?: object;
  interceptor?: {
    requestInterceptor: Array<Interceptor["requestInterceptor"]>;
    responseInterceptor: Array<Interceptor["responseInterceptor"]>;
    errorInterceptor: Array<Interceptor["errorInterceptor"]>;
  };
}

const setGlobalConfig = (config: FetchConfig) => {
  // fetchOption 只能为 undefined 和 object

  if (config.fetchOption) {
    invariant(
      isPlainObject(config.fetchOption),
      `[fetch] fetchOption should be plain object , but got ${typeof config.fetchOption}`
    );
  }

  // prefix 只能为 undefined 和 string

  if (config.prefix) {
    invariant(
      isString(config.prefix),
      `[fetch] prefix should be string , but got ${typeof config.prefix}`
    );
  }

  // interceptor 只能为 undefined 和 object

  if (config.interceptor) {
    invariant(
      isPlainObject(config.interceptor),
      `[fetch] interceptor should be plain object , but got ${typeof config.interceptor}`
    );

    // 每一种的 interceptor 只能为 undefined 和 Array<Function>

    Object.keys(config.interceptor).forEach(key => {
      if (config.interceptor[key]) {
        invariant(
          isArray(config.interceptor[key]),
          `[fetch] each interceptor should be array , but got ${typeof config
            .interceptor[key]}`
        );

        config.interceptor[key].forEach(v => {
          invariant(
            isFunction(v),
            `[fetch] each interceptor should be Array<Function> , but got ${typeof v}`
          );
        });
      }
    });
  }

  const prefix =
    config.prefix !== undefined ? config.prefix : DEFAULT_CONFIG.prefix;

  const fetchOption = Object.assign(
    {},
    config.fetchOption || {},
    DEFAULT_CONFIG.fetchOption
  );

  const interceptor = Object.keys(DEFAULT_CONFIG.interceptor).reduce(
    (p, key) => {
      const fns = DEFAULT_CONFIG.interceptor[key].concat(
        config.interceptor[key]
      );
      p[key] = compose(fns);
      return p;
    },
    {}
  );

  globalConfig.set("prefix", prefix);
  globalConfig.set("fetchOption", fetchOption);
  globalConfig.set("interceptor", interceptor);

  return fetchWebapi;
};

export default setGlobalConfig;
export * from "./fetch";
