/*
 * 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 { safeParse } from "../../lib/schemas.js";
import * as openEnums from "../../types/enums.js";
import { OpenEnum } from "../../types/enums.js";
import { Result as SafeParseResult } from "../../types/fp.js";
import { smartUnion } from "../../types/smartUnion.js";
import { SDKValidationError } from "../errors/sdkvalidationerror.js";
import {
  CustomerStateSubscriptionMeter,
  CustomerStateSubscriptionMeter$inboundSchema,
  CustomerStateSubscriptionMeter$Outbound,
  CustomerStateSubscriptionMeter$outboundSchema,
} from "./customerstatesubscriptionmeter.js";
import {
  MetadataOutputType,
  MetadataOutputType$inboundSchema,
  MetadataOutputType$Outbound,
  MetadataOutputType$outboundSchema,
} from "./metadataoutputtype.js";
import {
  RecurringInterval,
  RecurringInterval$inboundSchema,
  RecurringInterval$outboundSchema,
} from "./recurringinterval.js";

export type CustomerStateSubscriptionCustomFieldData =
  | string
  | number
  | boolean
  | Date;

export const Status = {
  Active: "active",
  Trialing: "trialing",
} as const;
export type Status = OpenEnum<typeof Status>;

/**
 * An active customer subscription.
 */
export type CustomerStateSubscription = {
  /**
   * The ID of the subscription.
   */
  id: string;
  /**
   * Creation timestamp of the object.
   */
  createdAt: Date;
  /**
   * Last modification timestamp of the object.
   */
  modifiedAt: Date | null;
  /**
   * Key-value object storing custom field values.
   */
  customFieldData?:
    | { [k: string]: string | number | boolean | Date | null }
    | undefined;
  metadata: { [k: string]: MetadataOutputType };
  status: Status;
  /**
   * The amount of the subscription.
   */
  amount: number;
  /**
   * The currency of the subscription.
   */
  currency: string;
  recurringInterval: RecurringInterval;
  /**
   * The start timestamp of the current billing period.
   */
  currentPeriodStart: Date;
  /**
   * The end timestamp of the current billing period.
   */
  currentPeriodEnd: Date;
  /**
   * The start timestamp of the trial period, if any.
   */
  trialStart: Date | null;
  /**
   * The end timestamp of the trial period, if any.
   */
  trialEnd: Date | null;
  /**
   * Whether the subscription will be canceled at the end of the current period.
   */
  cancelAtPeriodEnd: boolean;
  /**
   * The timestamp when the subscription was canceled. The subscription might still be active if `cancel_at_period_end` is `true`.
   */
  canceledAt: Date | null;
  /**
   * The timestamp when the subscription started.
   */
  startedAt: Date | null;
  /**
   * The timestamp when the subscription will end.
   */
  endsAt: Date | null;
  /**
   * The ID of the subscribed product.
   */
  productId: string;
  /**
   * The ID of the applied discount, if any.
   */
  discountId: string | null;
  /**
   * List of meters associated with the subscription.
   */
  meters: Array<CustomerStateSubscriptionMeter>;
};

/** @internal */
export const CustomerStateSubscriptionCustomFieldData$inboundSchema:
  z.ZodMiniType<CustomerStateSubscriptionCustomFieldData, unknown> = smartUnion(
    [
      z.string(),
      z.int(),
      z.boolean(),
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ],
  );
/** @internal */
export type CustomerStateSubscriptionCustomFieldData$Outbound =
  | string
  | number
  | boolean
  | string;

/** @internal */
export const CustomerStateSubscriptionCustomFieldData$outboundSchema:
  z.ZodMiniType<
    CustomerStateSubscriptionCustomFieldData$Outbound,
    CustomerStateSubscriptionCustomFieldData
  > = smartUnion([
    z.string(),
    z.int(),
    z.boolean(),
    z.pipe(z.date(), z.transform(v => v.toISOString())),
  ]);

export function customerStateSubscriptionCustomFieldDataToJSON(
  customerStateSubscriptionCustomFieldData:
    CustomerStateSubscriptionCustomFieldData,
): string {
  return JSON.stringify(
    CustomerStateSubscriptionCustomFieldData$outboundSchema.parse(
      customerStateSubscriptionCustomFieldData,
    ),
  );
}
export function customerStateSubscriptionCustomFieldDataFromJSON(
  jsonString: string,
): SafeParseResult<
  CustomerStateSubscriptionCustomFieldData,
  SDKValidationError
> {
  return safeParse(
    jsonString,
    (x) =>
      CustomerStateSubscriptionCustomFieldData$inboundSchema.parse(
        JSON.parse(x),
      ),
    `Failed to parse 'CustomerStateSubscriptionCustomFieldData' from JSON`,
  );
}

/** @internal */
export const Status$inboundSchema: z.ZodMiniType<Status, unknown> = openEnums
  .inboundSchema(Status);
/** @internal */
export const Status$outboundSchema: z.ZodMiniType<string, Status> = openEnums
  .outboundSchema(Status);

/** @internal */
export const CustomerStateSubscription$inboundSchema: z.ZodMiniType<
  CustomerStateSubscription,
  unknown
> = z.pipe(
  z.object({
    id: z.string(),
    created_at: z.pipe(
      z.iso.datetime({ offset: true }),
      z.transform(v => new Date(v)),
    ),
    modified_at: z.nullable(
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ),
    custom_field_data: z.optional(
      z.record(
        z.string(),
        z.nullable(
          smartUnion([
            z.string(),
            z.int(),
            z.boolean(),
            z.pipe(
              z.iso.datetime({ offset: true }),
              z.transform(v => new Date(v)),
            ),
          ]),
        ),
      ),
    ),
    metadata: z.record(z.string(), MetadataOutputType$inboundSchema),
    status: Status$inboundSchema,
    amount: z.int(),
    currency: z.string(),
    recurring_interval: RecurringInterval$inboundSchema,
    current_period_start: z.pipe(
      z.iso.datetime({ offset: true }),
      z.transform(v => new Date(v)),
    ),
    current_period_end: z.pipe(
      z.iso.datetime({ offset: true }),
      z.transform(v => new Date(v)),
    ),
    trial_start: z.nullable(
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ),
    trial_end: z.nullable(
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ),
    cancel_at_period_end: z.boolean(),
    canceled_at: z.nullable(
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ),
    started_at: z.nullable(
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ),
    ends_at: z.nullable(
      z.pipe(z.iso.datetime({ offset: true }), z.transform(v => new Date(v))),
    ),
    product_id: z.string(),
    discount_id: z.nullable(z.string()),
    meters: z.array(CustomerStateSubscriptionMeter$inboundSchema),
  }),
  z.transform((v) => {
    return remap$(v, {
      "created_at": "createdAt",
      "modified_at": "modifiedAt",
      "custom_field_data": "customFieldData",
      "recurring_interval": "recurringInterval",
      "current_period_start": "currentPeriodStart",
      "current_period_end": "currentPeriodEnd",
      "trial_start": "trialStart",
      "trial_end": "trialEnd",
      "cancel_at_period_end": "cancelAtPeriodEnd",
      "canceled_at": "canceledAt",
      "started_at": "startedAt",
      "ends_at": "endsAt",
      "product_id": "productId",
      "discount_id": "discountId",
    });
  }),
);
/** @internal */
export type CustomerStateSubscription$Outbound = {
  id: string;
  created_at: string;
  modified_at: string | null;
  custom_field_data?:
    | { [k: string]: string | number | boolean | string | null }
    | undefined;
  metadata: { [k: string]: MetadataOutputType$Outbound };
  status: string;
  amount: number;
  currency: string;
  recurring_interval: string;
  current_period_start: string;
  current_period_end: string;
  trial_start: string | null;
  trial_end: string | null;
  cancel_at_period_end: boolean;
  canceled_at: string | null;
  started_at: string | null;
  ends_at: string | null;
  product_id: string;
  discount_id: string | null;
  meters: Array<CustomerStateSubscriptionMeter$Outbound>;
};

/** @internal */
export const CustomerStateSubscription$outboundSchema: z.ZodMiniType<
  CustomerStateSubscription$Outbound,
  CustomerStateSubscription
> = z.pipe(
  z.object({
    id: z.string(),
    createdAt: z.pipe(z.date(), z.transform(v => v.toISOString())),
    modifiedAt: z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
    customFieldData: z.optional(
      z.record(
        z.string(),
        z.nullable(
          smartUnion([
            z.string(),
            z.int(),
            z.boolean(),
            z.pipe(z.date(), z.transform(v => v.toISOString())),
          ]),
        ),
      ),
    ),
    metadata: z.record(z.string(), MetadataOutputType$outboundSchema),
    status: Status$outboundSchema,
    amount: z.int(),
    currency: z.string(),
    recurringInterval: RecurringInterval$outboundSchema,
    currentPeriodStart: z.pipe(z.date(), z.transform(v => v.toISOString())),
    currentPeriodEnd: z.pipe(z.date(), z.transform(v => v.toISOString())),
    trialStart: z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
    trialEnd: z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
    cancelAtPeriodEnd: z.boolean(),
    canceledAt: z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
    startedAt: z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
    endsAt: z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
    productId: z.string(),
    discountId: z.nullable(z.string()),
    meters: z.array(CustomerStateSubscriptionMeter$outboundSchema),
  }),
  z.transform((v) => {
    return remap$(v, {
      createdAt: "created_at",
      modifiedAt: "modified_at",
      customFieldData: "custom_field_data",
      recurringInterval: "recurring_interval",
      currentPeriodStart: "current_period_start",
      currentPeriodEnd: "current_period_end",
      trialStart: "trial_start",
      trialEnd: "trial_end",
      cancelAtPeriodEnd: "cancel_at_period_end",
      canceledAt: "canceled_at",
      startedAt: "started_at",
      endsAt: "ends_at",
      productId: "product_id",
      discountId: "discount_id",
    });
  }),
);

export function customerStateSubscriptionToJSON(
  customerStateSubscription: CustomerStateSubscription,
): string {
  return JSON.stringify(
    CustomerStateSubscription$outboundSchema.parse(customerStateSubscription),
  );
}
export function customerStateSubscriptionFromJSON(
  jsonString: string,
): SafeParseResult<CustomerStateSubscription, SDKValidationError> {
  return safeParse(
    jsonString,
    (x) => CustomerStateSubscription$inboundSchema.parse(JSON.parse(x)),
    `Failed to parse 'CustomerStateSubscription' from JSON`,
  );
}
