import type { IInterceptor, IBaseRequestOptions, IBaseRequestParam } from '../types';

/**
 * 网络请求的基类，统一封装网络请求流程：
 * 发送前处理 -> 发送请求 -> 数据返回处理
 * 以及异常错误处理
 * 发送请求使用抽象工厂模式实现，支持不同平台的定制实现
 */
export abstract class BaseRequest {
  requestInterceptors: IInterceptor[] = [];
  responseInterceptors: IInterceptor[] = [];
  errorInterceptors: IInterceptor[] = [];

  protected constructor(options: IBaseRequestOptions) {
    if (options?.requestInterceptors) {
      this.requestInterceptors = options.requestInterceptors;
    }
    if (options?.responseInterceptors) {
      this.responseInterceptors = options.responseInterceptors;
    }
    if (options?.errorInterceptors) {
      this.errorInterceptors = options.errorInterceptors;
    }
  }

  /**
   * 统一封装发送请求流程
   * @param param 请求参数
   * @param customInterceptor 自定义拦截处理
   */
  async send(
    param: IBaseRequestParam,
    customInterceptor: {
      customRequestInterceptorsHead: IInterceptor[],
      customRequestInterceptorsTail: IInterceptor[],
      customResponseInterceptorsHead: IInterceptor[],
      customResponseInterceptorsTail: IInterceptor[],
      customErrorInterceptorsHead: IInterceptor[],
      customErrorInterceptorsTail: IInterceptor[],
    } = {
      customRequestInterceptorsHead: [],
      customRequestInterceptorsTail: [],
      customResponseInterceptorsHead: [],
      customResponseInterceptorsTail: [],
      customErrorInterceptorsHead: [],
      customErrorInterceptorsTail: [],
    },
  ) {
    // return new Promise((resolve, reject) => {
    // 请求前拦截处理
    const [stop, interceptedParam] = await this.interceptBeforeSend(customInterceptor, param);
    if (stop) {
      return Promise.reject(interceptedParam);
    }
    try {
      const res = await this.doSend(param);
      // 返回数据后拦截处理
      const [stop, interceptedRes] = await this.interceptAfterResponse(customInterceptor, res, param);
      if (stop) {
        return Promise.reject(interceptedRes);
      }
      return (interceptedRes);
    } catch (err) {
      // 网络错误拦截处理
      const [, interceptedErr] = await this.interceptError(customInterceptor, err, param);
      return Promise.reject(interceptedErr);
    }
    // });
  }

  /**
   * 错误处理
   * @param customInterceptor 自定义拦截处理
   * @param err 出现的错误
   * @param param 请求参数
   * @private
   */
  private async interceptError(customInterceptor: {
    customRequestInterceptorsHead: IInterceptor[];
    customRequestInterceptorsTail: IInterceptor[];
    customResponseInterceptorsHead: IInterceptor[];
    customResponseInterceptorsTail: IInterceptor[];
    customErrorInterceptorsHead: IInterceptor[];
    customErrorInterceptorsTail: IInterceptor[]
  }, err: any, param: IBaseRequestParam) {
    let interceptedErr = err;
    let stop = false;
    let { errorInterceptors } = this;
    if (customInterceptor?.customErrorInterceptorsHead) {
      errorInterceptors = customInterceptor.customErrorInterceptorsHead.concat(errorInterceptors);
    }
    if (customInterceptor?.customErrorInterceptorsTail) {
      errorInterceptors = errorInterceptors.concat(customInterceptor.customErrorInterceptorsTail);
    }
    for (const interceptor of errorInterceptors) {
      [stop, interceptedErr] = await interceptor.interceptor(interceptedErr, param);
      if (stop) {
        break;
      }
    }
    return [stop, interceptedErr];
  }

  /**
   * 发送请求拦截处理
   * @param customInterceptor 自定义拦截处理
   * @param param 请求参数
   * @private
   */
  private async interceptBeforeSend(customInterceptor: {
    customRequestInterceptorsHead: IInterceptor[];
    customRequestInterceptorsTail: IInterceptor[];
    customResponseInterceptorsHead: IInterceptor[];
    customResponseInterceptorsTail: IInterceptor[];
    customErrorInterceptorsHead: IInterceptor[];
    customErrorInterceptorsTail: IInterceptor[]
  }, param: IBaseRequestParam) {
    let stop = false;
    let interceptedParam = param;
    let { requestInterceptors } = this;
    if (customInterceptor?.customRequestInterceptorsHead) {
      requestInterceptors = customInterceptor.customRequestInterceptorsHead.concat(requestInterceptors);
    }
    if (customInterceptor?.customRequestInterceptorsTail) {
      requestInterceptors = requestInterceptors.concat(customInterceptor.customRequestInterceptorsTail);
    }
    for (const interceptor of requestInterceptors) {
      [stop, interceptedParam] = await interceptor.interceptor(interceptedParam, null);
      if (stop) {
        break;
      }
    }
    return [stop, interceptedParam];
  }

  /**
   * 返回数据拦截处理
   * @param customInterceptor 自定义拦截处理
   * @param res 返回数据
   * @param param 请求参数
   * @private
   */
  private async interceptAfterResponse(customInterceptor: {
    customRequestInterceptorsHead: IInterceptor[];
    customRequestInterceptorsTail: IInterceptor[];
    customResponseInterceptorsHead: IInterceptor[];
    customResponseInterceptorsTail: IInterceptor[];
    customErrorInterceptorsHead: IInterceptor[];
    customErrorInterceptorsTail: IInterceptor[]
  }, res: any, param: IBaseRequestParam) {
    let interceptedRes = res;
    let stop = false;
    let { responseInterceptors } = this;
    if (customInterceptor?.customResponseInterceptorsHead) {
      responseInterceptors = customInterceptor.customResponseInterceptorsHead.concat(responseInterceptors);
    }
    if (customInterceptor?.customResponseInterceptorsTail) {
      responseInterceptors = responseInterceptors.concat(customInterceptor.customResponseInterceptorsTail);
    }
    for (const interceptor of responseInterceptors) {
      [stop, interceptedRes] = await interceptor.interceptor(interceptedRes, param);
      if (stop) {
        break;
      }
    }
    return [stop, interceptedRes];
  }

  abstract doSend(param: IBaseRequestParam): Promise<any>;
}
