type JsonStringifyRest = Parameters<typeof JSON.stringify> extends [Error, ...infer R] ? R : never;

const prepareSerializableError = (error: Error | unknown) => {
  if (!(error instanceof Error)) return;

  const serializableError: Record<string, string | undefined> = {
    name: error.name || error.constructor.name || 'Unknown Error',
    message: error.message,
    cause: error.cause as string,
    stack: undefined,
  };

  for (const key of Object.getOwnPropertyNames(error)) {
    if (!(key in serializableError)) {
      serializableError[key] = (error as unknown as Record<string, string>)[key];
    }
  }

  return serializableError;
};

export const stringifyError = (error: Error | unknown, ...rest: JsonStringifyRest) =>
  JSON.stringify(prepareSerializableError(error), ...rest);
