import { queryString } from "@dage/utils";
import { DageRequestConfig, DageRequestMethod } from "./types";

/**
 * 转换 Headers 为 对象形式
 * @param headers
 */
export function headersToObject(headers: Headers): Record<string, string> {
  return Array.from(headers.entries()).reduce<Record<string, string>>(
    (prev, cur) => {
      const [key, value] = cur as [string, string];
      prev[key] = value;
      return prev;
    },
    {}
  );
}

/**
 * 能携带参数的请求方法
 * @param method
 */
export function methodsHasBody(method: DageRequestMethod) {
  return method !== "GET" && method !== "HEAD";
}

/**
 * 序列化载荷
 * @param headers
 * @param body
 */
export function serializeBody(headers: Record<string, string>, body: any) {
  if (body == null) {
    return body;
  }

  if (isArrayBuffer(body) || isBlob(body) || isFormData(body)) {
    return body;
  }

  const contentType = headers["content-type"];

  if (contentType === "application/x-www-form-urlencoded") {
    // 序列化为查询字符串
    return queryString.stringify(body);
  }

  return JSON.stringify(body);
}

export function isFormData(value: any): boolean {
  return typeof FormData !== "undefined" && value instanceof FormData;
}

export function isBlob(value: any): boolean {
  return typeof Blob !== "undefined" && value instanceof Blob;
}

export function isArrayBuffer(value: any): boolean {
  return typeof ArrayBuffer !== "undefined" && value instanceof ArrayBuffer;
}

/**
 * 根据body生成对应的contentType
 * @param body http body
 */
export function detectContentType(body: any): string | null {
  if (body == null) {
    return null;
  }
  if (isFormData(body) || isArrayBuffer(body)) {
    return null;
  }
  if (isBlob(body)) {
    return body.type || null;
  }

  if (
    typeof body === "object" ||
    typeof body === "number" ||
    Array.isArray(body)
  ) {
    return "application/json;charset=UTF-8";
  }

  return "application/x-www-form-urlencoded;charset=UTF-8";
}

export function getResponseType(
  config: DageRequestConfig
): DageRequestMeta["responseType"] {
  const meta = config.meta;
  return meta?.responseType || "json";
}

export function serializeResponseBody(
  res: globalThis.Response,
  config: DageRequestConfig
): Promise<Record<string, any> & { data: any }> {
  const responseType = getResponseType(config);

  switch (responseType) {
    case "arrayBuffer":
      return res.arrayBuffer().then((data) => ({ data }));
    case "blob":
      return res.blob().then((data) => ({ data }));
    case "json":
      return res.json();
    case "text":
      return res.text().then((data) => ({ data }));
    default:
      return Promise.reject(new Error("传入的meta.responseType 不符合规范"));
  }
}
