import baseUtil from '../../utils/base';
import errUtil from '../../utils/error';
import event, { EVENTS } from '../event';
import { ERR_UNKNOW_API, ERR_PARAMS } from '../consts';
import checker from '../../utils/checker';
import { sysLogger } from '../logger';

/**
 * API参数校验
 * @param {string} moduleName 模块名
 * @param {string} api API名
 * @param {Array<any>} params 参数
 */
export function checkParams(moduleName, api, params) {
  const { pass, msg, level } = checker.getAPIChecker(moduleName, api)(...params);
  if (!pass) {
    const error = errUtil.pkgErr(ERR_PARAMS, msg, moduleName, api);
    event.emit(EVENTS.ERR_PARAM, { moduleName, api, params, err: error });
    if (checker.CHECK_LEVEL.ERROR === level) {
      throw errUtil.pkgErr(ERR_PARAMS, msg)
    }
    sysLogger.warn(error.message);
  }
}

/**
 * 调用API处理，调用过程发消息
 * @param {() => (() => any)} genApiFun api生成器
 * @param {string} moduleName 模块名
 * @param {string} api API名
 * @param {Array<any>} params 参数
 * @returns 
 */
export async function callAPI(genApiFun, moduleName, api, params) {
  const at = Date.now()
  try {
    // 存在校验
    event.emit(EVENTS.API_CALL, { moduleName, api, params, at });
    const apiFun = genApiFun(moduleName, api)
    if (!baseUtil.isFun(apiFun)) {
      throw errUtil.pkgErr(ERR_UNKNOW_API);
    }

    // 参数校验
    checkParams(moduleName, api, params)

    // 正式调用
    const res = await apiFun(...params);
    event.emit(EVENTS.API_RESOLVE, { moduleName, api, params, res, dur: Date.now() - at });
    return res
  } catch (err) {
    const nerr = errUtil.pkgErr(err, null, moduleName, api);
    event.emit(EVENTS.ERR_REJECT, { moduleName, api, params, err: nerr, dur: Date.now() - at });
    throw nerr
  }
}

/**
 * 同步调用
 * @param {() => (() => any)} genApiFun 
 * @param {string} moduleName 
 * @param {string} api 
 * @param {Array<any>} params 
 * @returns 
 */
export function syncCallAPI(genApiFun, moduleName, api, params) {
  const at = Date.now()
  try {
    // 存在校验
    event.emit(EVENTS.API_CALL, { moduleName, api, params, at });
    const apiFun = genApiFun(moduleName, api)
    if (!baseUtil.isFun(apiFun)) {
      throw errUtil.pkgErr(ERR_UNKNOW_API);
    }

    // 参数校验
    checkParams(moduleName, api, params)

    // 正式调用
    const res = apiFun(...params);
    event.emit(EVENTS.API_RESOLVE, { moduleName, api, params, res, dur: Date.now() - at });
    return res
  } catch (err) {
    const nerr = errUtil.pkgErr(err, null, moduleName, api);
    event.emit(EVENTS.ERR_REJECT, { moduleName, api, params, err: nerr, dur: Date.now() - at });
    throw nerr
  }
}
