const appendValue = (formData: FormData, key: string, value: unknown, arrayDepth = 0) => {
  if (value instanceof Buffer) {
    formData.append(key, new Blob([value]));
    return;
  }
  if (value instanceof Blob) {
    formData.append(key, value);
    return;
  }
  if (value instanceof File) {
    formData.append(key, value, value.name);
    return;
  }
  if (typeof value === 'string') {
    formData.append(key, value);
    return;
  }
  if (typeof value === 'number' && !Number.isNaN(value)) {
    formData.append(key, value.toString(10));
    return;
  }
  if (typeof value === 'boolean') {
    formData.append(key, value.toString());
    return;
  }
  if (Array.isArray(value) && arrayDepth === 0) {
    appendValue(formData, key, value, arrayDepth + 1);
    return;
  }
  if (typeof value === 'object' && value !== null) {
    formData.append(key, JSON.stringify(value));
    return;
  }
  throw new Error(`Invalid value for key: ${key}`);
};

export const fromJson = (json: Record<string, unknown>) => {
  const formData = new FormData();
  Object
    .entries(json)
    .forEach(([key, value]) => {
      appendValue(formData, key, value);
    });
  return formData;
};

export const toJson = (formData: FormData) => {
  const json = {} as Record<string, unknown>;
  formData.forEach((value, key) => {
    json[key] = value;
  });
  return json;
};
