/*
 * Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
 */

import * as z from "zod/v4-mini";
import { SDKValidationError } from "../models/errors/sdkvalidationerror.js";
import { ERR, OK, Result } from "../types/fp.js";

/**
 * Utility function that executes some code which may throw a ZodError. It
 * intercepts this error and converts it to an SDKValidationError so as to not
 * leak Zod implementation details to user code.
 */
export function parse<Inp, Out>(
  rawValue: Inp,
  fn: (value: Inp) => Out,
  errorMessage: string,
): Out {
  try {
    return fn(rawValue);
  } catch (err) {
    if (err instanceof z.core.$ZodError) {
      throw new SDKValidationError(errorMessage, err, rawValue);
    }
    throw err;
  }
}

/**
 * Utility function that executes some code which may result in a ZodError. It
 * intercepts this error and converts it to an SDKValidationError so as to not
 * leak Zod implementation details to user code.
 */
export function safeParse<Inp, Out>(
  rawValue: Inp,
  fn: (value: Inp) => Out,
  errorMessage: string,
): Result<Out, SDKValidationError> {
  try {
    return OK(fn(rawValue));
  } catch (err) {
    return ERR(new SDKValidationError(errorMessage, err, rawValue));
  }
}

export function collectExtraKeys<
  Shape extends z.core.$ZodShape,
  Catchall extends z.ZodMiniType,
  K extends string,
  Optional extends boolean,
>(
  obj: z.ZodMiniObject<Shape, z.core.$catchall<Catchall>>,
  extrasKey: K,
  optional: Optional,
): z.ZodMiniPipe<
  z.ZodMiniObject<Shape, z.core.$catchall<Catchall>>,
  z.ZodMiniTransform<
    & z.output<z.ZodMiniObject<Shape, z.core.$strip>>
    & (Optional extends false ? {
        [k in K]: Record<string, z.output<Catchall>>;
      }
      : {
        [k in K]?: Record<string, z.output<Catchall>> | undefined;
      }),
    z.output<z.ZodMiniObject<Shape, z.core.$catchall<Catchall>>>
  >
> {
  return z.pipe(
    obj,
    z.transform((val: any) => {
      const extras: Record<string, z.output<Catchall>> = {};
      const { shape } = obj;
      for (const [key] of Object.entries(val)) {
        if (key in shape) {
          continue;
        }

        const v = val[key];
        if (typeof v === "undefined") {
          continue;
        }

        extras[key] = v;
        delete val[key];
      }

      if (optional && Object.keys(extras).length === 0) {
        return val;
      }

      return { ...val, [extrasKey]: extras };
    }),
  );
}
