import { login } from "../logic";
import { request as _request } from "../wx/network";
import { getAccountInfoSync } from "../wx/open-api";

const shareRequestCache = new Map<string, IRequestData<any>>();


const miniProgram = getAccountInfoSync();
export function createRequest(option: IRequestCreateConfig) {
  const { baseURL } = option;

  return async function request<R, T>(config: IRequestConfig<R, T>) {
    let {
      url,
      data,
      params,
      header,
      meta,
      notTransform = false,
      transform = (params: any) => params,
      shareRequest,
      ..._config
    } = config;

    if (config.method === "GET") {
      data = params;
    } else if (params) {
      const query = Object.entries(params).map(
        ([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`
      );
      url += `?${query.join("&")}`;
    }

    const key = url;
    if (shareRequest && shareRequestCache.has(key)) {
      return shareRequestCache.get(key) as unknown as PromiseLike<
        IRequestData<T>
      >;
    }

    header ??= {};
    header["Authorization"] = meta?.ignoreToken
      ? ""
      : (await option.token?.()) ?? "";
    header["patientId"] = wx.getStorageSync("patientId") ?? "";
    // header['patientId'] = '783';
    header["doctorId"] = wx.getStorageSync("doctorId") ?? "";
    header["scene"] = wx.getStorageSync("scene") ?? "";
    header["appId"] = miniProgram.appId ?? "";
    header["version"] = miniProgram.version ?? "";
    header["env"] = miniProgram.envVersion ?? "";
    const promise = _request<IRequestData<T>>({
      url: /https?\:\/\//.test(url) ? url : `${baseURL}${url}`,
      header,
      data,
      ..._config,
    }).then((response) => {
      if (response.statusCode === 200) {
        if (notTransform) return response.data;
        if (response.data.code === 200 && response.data.success !== false) {
          const data =
            Array.isArray(response.data.rows) && response.data.total != null
              ? { data: response.data.rows, total: response.data.total }
              : response.data.data;
          return transform({ data: data as any, header: response.header });
        }
        throw {
          errMsg: response.data.msg || `app:${response.data.code}`,
          errno: `060202${response.data.code}`,
        };
      }
      throw {
        errMsg: `${response.errMsg}:${response.statusCode}`,
        errno: `060201${response.statusCode}`,
      };
    });

    if (shareRequest) shareRequestCache.set(key, <any>promise);

    return (promise as any).catch(async (error: { errno: string }) => {
      shareRequestCache.delete(key);
      if (error.errno === "060201401") {
        await login(true, "重新登录中");
        wx.showLoading({ title: "重新加载中" });
        try {
          return await request(config);
        } catch (error) {
          throw error;
        } finally {
          wx.hideLoading();
        }
      }
      throw error;
    });
  };
}
