import { withResolvers } from "../promise";

type Data = string | Record<string, any> | ArrayBuffer;
type Option<T extends Data = Data> = Omit<WechatMiniprogram.RequestOption<T>, 'success' | 'fail' | 'complete'>;
export type Request<T> = PromiseLike<T> & {
  abort: () => void;
  onProgressUpdate: (listener: WechatMiniprogram.UploadTaskOnProgressUpdateCallback) => () => void;
};

export function request<T extends Data>(option: Option<T>) {
  type Result = WechatMiniprogram.RequestSuccessCallbackResult<T>
  const { promise, resolve, reject } = withResolvers<Result, Request<Result>>();

  const task = wx.request({ ...option, success: resolve, fail: reject, });
  promise.abort = () => {
    task.abort();
    task.offHeadersReceived();
    task.offChunkReceived();
  }
  return promise
}

type UploadOption = Omit<WechatMiniprogram.UploadFileOption, 'success' | 'fail' | 'complete'>;
export function upload<T extends string>(option: UploadOption, fn: (data: string) => T): Request<T> {
  const { promise, resolve, reject } = withResolvers<T, Request<T>>();
  const task = wx.uploadFile({
    ...option, success(res) {
      if (res.statusCode !== 200) reject({ errMsg: `上传失败(${res.statusCode})` })
      else resolve(fn(res.data));
    }, fail: reject,
  });
  promise.abort = () => {
    task.abort();
    task.offHeadersReceived();
    task.offProgressUpdate();
  }
  promise.onProgressUpdate = (listener: WechatMiniprogram.UploadTaskOnProgressUpdateCallback) => {
    task.onProgressUpdate(listener);
    return () => task.offProgressUpdate(listener);
  }
  return promise;
}