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

import * as z from "zod/v4-mini";
import { remap as remap$ } from "../../lib/primitives.js";
import { smartUnion } from "../../types/smartUnion.js";
import {
  AttachedCustomFieldCreate,
  AttachedCustomFieldCreate$Outbound,
  AttachedCustomFieldCreate$outboundSchema,
} from "./attachedcustomfieldcreate.js";
import {
  ProductPriceCustomCreate,
  ProductPriceCustomCreate$Outbound,
  ProductPriceCustomCreate$outboundSchema,
} from "./productpricecustomcreate.js";
import {
  ProductPriceFixedCreate,
  ProductPriceFixedCreate$Outbound,
  ProductPriceFixedCreate$outboundSchema,
} from "./productpricefixedcreate.js";
import {
  ProductPriceMeteredUnitCreate,
  ProductPriceMeteredUnitCreate$Outbound,
  ProductPriceMeteredUnitCreate$outboundSchema,
} from "./productpricemeteredunitcreate.js";
import {
  ProductPriceSeatBasedCreate,
  ProductPriceSeatBasedCreate$Outbound,
  ProductPriceSeatBasedCreate$outboundSchema,
} from "./productpriceseatbasedcreate.js";
import {
  ProductVisibility,
  ProductVisibility$outboundSchema,
} from "./productvisibility.js";
import {
  RecurringInterval,
  RecurringInterval$outboundSchema,
} from "./recurringinterval.js";
import {
  TrialInterval,
  TrialInterval$outboundSchema,
} from "./trialinterval.js";

export type ProductCreateRecurringMetadata = string | number | number | boolean;

export type ProductCreateRecurringPrices =
  | ProductPriceCustomCreate
  | ProductPriceFixedCreate
  | ProductPriceMeteredUnitCreate
  | ProductPriceSeatBasedCreate;

export type ProductCreateRecurring = {
  /**
   * Key-value object allowing you to store additional information.
   *
   * @remarks
   *
   * The key must be a string with a maximum length of **40 characters**.
   * The value must be either:
   *
   * * A string with a maximum length of **500 characters**
   * * An integer
   * * A floating-point number
   * * A boolean
   *
   * You can store up to **50 key-value pairs**.
   */
  metadata?: { [k: string]: string | number | number | boolean } | undefined;
  /**
   * The name of the product.
   */
  name: string;
  /**
   * The description of the product.
   */
  description?: string | null | undefined;
  visibility?: ProductVisibility | undefined;
  /**
   * List of available prices for this product. It may combine at most one fixed price with one seat-based price (billed as `fixed + seat_charge`), or contain a single custom or free price, plus any number of metered prices. A free price cannot be combined with other prices, and a custom price cannot be combined with a fixed or seat-based price. Metered prices are not supported on one-time purchase products.
   */
  prices: Array<
    | ProductPriceCustomCreate
    | ProductPriceFixedCreate
    | ProductPriceMeteredUnitCreate
    | ProductPriceSeatBasedCreate
  >;
  /**
   * List of file IDs. Each one must be on the same organization as the product, of type `product_media` and correctly uploaded.
   */
  medias?: Array<string> | null | undefined;
  /**
   * List of custom fields to attach.
   */
  attachedCustomFields?: Array<AttachedCustomFieldCreate> | undefined;
  /**
   * The ID of the organization owning the product. **Required unless you use an organization token.**
   */
  organizationId?: string | null | undefined;
  /**
   * The interval unit for the trial period.
   */
  trialInterval?: TrialInterval | null | undefined;
  /**
   * The number of interval units for the trial period.
   */
  trialIntervalCount?: number | null | undefined;
  recurringInterval: RecurringInterval;
  /**
   * Number of interval units of the subscription. If this is set to 1 the charge will happen every interval (e.g. every month), if set to 2 it will be every other month, and so on.
   */
  recurringIntervalCount?: number | undefined;
  /**
   * Optional meter cycle, independent of the billing interval. When set, overage settlement, meter resets and meter-credit grants run on this cadence rather than the billing interval — e.g. yearly billing with monthly credits. It must evenly divide the billing interval. If `None`, metered concerns follow the billing interval. **Once set, it can't be changed.**
   */
  meterInterval?: RecurringInterval | null | undefined;
  /**
   * Number of meter interval units. Defaults to 1 when `meter_interval` is set. Ignored when `meter_interval` is `None`.
   */
  meterIntervalCount?: number | null | undefined;
};

/** @internal */
export type ProductCreateRecurringMetadata$Outbound =
  | string
  | number
  | number
  | boolean;

/** @internal */
export const ProductCreateRecurringMetadata$outboundSchema: z.ZodMiniType<
  ProductCreateRecurringMetadata$Outbound,
  ProductCreateRecurringMetadata
> = smartUnion([z.string(), z.int(), z.number(), z.boolean()]);

export function productCreateRecurringMetadataToJSON(
  productCreateRecurringMetadata: ProductCreateRecurringMetadata,
): string {
  return JSON.stringify(
    ProductCreateRecurringMetadata$outboundSchema.parse(
      productCreateRecurringMetadata,
    ),
  );
}

/** @internal */
export type ProductCreateRecurringPrices$Outbound =
  | ProductPriceCustomCreate$Outbound
  | ProductPriceFixedCreate$Outbound
  | ProductPriceMeteredUnitCreate$Outbound
  | ProductPriceSeatBasedCreate$Outbound;

/** @internal */
export const ProductCreateRecurringPrices$outboundSchema: z.ZodMiniType<
  ProductCreateRecurringPrices$Outbound,
  ProductCreateRecurringPrices
> = z.union([
  ProductPriceCustomCreate$outboundSchema,
  ProductPriceFixedCreate$outboundSchema,
  ProductPriceMeteredUnitCreate$outboundSchema,
  ProductPriceSeatBasedCreate$outboundSchema,
]);

export function productCreateRecurringPricesToJSON(
  productCreateRecurringPrices: ProductCreateRecurringPrices,
): string {
  return JSON.stringify(
    ProductCreateRecurringPrices$outboundSchema.parse(
      productCreateRecurringPrices,
    ),
  );
}

/** @internal */
export type ProductCreateRecurring$Outbound = {
  metadata?: { [k: string]: string | number | number | boolean } | undefined;
  name: string;
  description?: string | null | undefined;
  visibility?: string | undefined;
  prices: Array<
    | ProductPriceCustomCreate$Outbound
    | ProductPriceFixedCreate$Outbound
    | ProductPriceMeteredUnitCreate$Outbound
    | ProductPriceSeatBasedCreate$Outbound
  >;
  medias?: Array<string> | null | undefined;
  attached_custom_fields?:
    | Array<AttachedCustomFieldCreate$Outbound>
    | undefined;
  organization_id?: string | null | undefined;
  trial_interval?: string | null | undefined;
  trial_interval_count?: number | null | undefined;
  recurring_interval: string;
  recurring_interval_count: number;
  meter_interval?: string | null | undefined;
  meter_interval_count?: number | null | undefined;
};

/** @internal */
export const ProductCreateRecurring$outboundSchema: z.ZodMiniType<
  ProductCreateRecurring$Outbound,
  ProductCreateRecurring
> = z.pipe(
  z.object({
    metadata: z.optional(
      z.record(
        z.string(),
        smartUnion([z.string(), z.int(), z.number(), z.boolean()]),
      ),
    ),
    name: z.string(),
    description: z.optional(z.nullable(z.string())),
    visibility: z.optional(ProductVisibility$outboundSchema),
    prices: z.array(
      z.union([
        ProductPriceCustomCreate$outboundSchema,
        ProductPriceFixedCreate$outboundSchema,
        ProductPriceMeteredUnitCreate$outboundSchema,
        ProductPriceSeatBasedCreate$outboundSchema,
      ]),
    ),
    medias: z.optional(z.nullable(z.array(z.string()))),
    attachedCustomFields: z.optional(
      z.array(AttachedCustomFieldCreate$outboundSchema),
    ),
    organizationId: z.optional(z.nullable(z.string())),
    trialInterval: z.optional(z.nullable(TrialInterval$outboundSchema)),
    trialIntervalCount: z.optional(z.nullable(z.int())),
    recurringInterval: RecurringInterval$outboundSchema,
    recurringIntervalCount: z._default(z.int(), 1),
    meterInterval: z.optional(z.nullable(RecurringInterval$outboundSchema)),
    meterIntervalCount: z.optional(z.nullable(z.int())),
  }),
  z.transform((v) => {
    return remap$(v, {
      attachedCustomFields: "attached_custom_fields",
      organizationId: "organization_id",
      trialInterval: "trial_interval",
      trialIntervalCount: "trial_interval_count",
      recurringInterval: "recurring_interval",
      recurringIntervalCount: "recurring_interval_count",
      meterInterval: "meter_interval",
      meterIntervalCount: "meter_interval_count",
    });
  }),
);

export function productCreateRecurringToJSON(
  productCreateRecurring: ProductCreateRecurring,
): string {
  return JSON.stringify(
    ProductCreateRecurring$outboundSchema.parse(productCreateRecurring),
  );
}
