/*
 * 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 { Result as SafeParseResult } from "../../types/fp.js";
import { SDKValidationError } from "../errors/sdkvalidationerror.js";
import {
  CountAggregation,
  CountAggregation$inboundSchema,
  CountAggregation$Outbound,
  CountAggregation$outboundSchema,
} from "./countaggregation.js";
import {
  Filter,
  Filter$inboundSchema,
  Filter$Outbound,
  Filter$outboundSchema,
} from "./filter.js";
import {
  MetadataOutputType,
  MetadataOutputType$inboundSchema,
  MetadataOutputType$Outbound,
  MetadataOutputType$outboundSchema,
} from "./metadataoutputtype.js";
import {
  MeterUnit,
  MeterUnit$inboundSchema,
  MeterUnit$outboundSchema,
} from "./meterunit.js";
import {
  PropertyAggregation,
  PropertyAggregation$inboundSchema,
  PropertyAggregation$Outbound,
  PropertyAggregation$outboundSchema,
} from "./propertyaggregation.js";
import {
  UniqueAggregation,
  UniqueAggregation$inboundSchema,
  UniqueAggregation$Outbound,
  UniqueAggregation$outboundSchema,
} from "./uniqueaggregation.js";

/**
 * The aggregation to apply on the filtered events to calculate the meter.
 */
export type MeterAggregation =
  | (PropertyAggregation & { func: "avg" })
  | CountAggregation
  | (PropertyAggregation & { func: "max" })
  | (PropertyAggregation & { func: "min" })
  | (PropertyAggregation & { func: "sum" })
  | UniqueAggregation;

export type Meter = {
  metadata: { [k: string]: MetadataOutputType };
  /**
   * Creation timestamp of the object.
   */
  createdAt: Date;
  /**
   * Last modification timestamp of the object.
   */
  modifiedAt: Date | null;
  /**
   * The ID of the object.
   */
  id: string;
  /**
   * The name of the meter. Will be shown on customer's invoices and usage.
   */
  name: string;
  unit: MeterUnit;
  /**
   * The label for the custom unit.
   */
  customLabel?: string | null | undefined;
  /**
   * The multiplier to convert from base unit to display scale.
   */
  customMultiplier?: number | null | undefined;
  filter: Filter;
  /**
   * The aggregation to apply on the filtered events to calculate the meter.
   */
  aggregation:
    | (PropertyAggregation & { func: "avg" })
    | CountAggregation
    | (PropertyAggregation & { func: "max" })
    | (PropertyAggregation & { func: "min" })
    | (PropertyAggregation & { func: "sum" })
    | UniqueAggregation;
  /**
   * The ID of the organization owning the meter.
   */
  organizationId: string;
  /**
   * Whether the meter is archived and the time it was archived.
   */
  archivedAt?: Date | null | undefined;
};

/** @internal */
export const MeterAggregation$inboundSchema: z.ZodMiniType<
  MeterAggregation,
  unknown
> = z.union([
  z.intersection(
    PropertyAggregation$inboundSchema,
    z.object({ func: z.literal("avg") }),
  ),
  CountAggregation$inboundSchema,
  z.intersection(
    PropertyAggregation$inboundSchema,
    z.object({ func: z.literal("max") }),
  ),
  z.intersection(
    PropertyAggregation$inboundSchema,
    z.object({ func: z.literal("min") }),
  ),
  z.intersection(
    PropertyAggregation$inboundSchema,
    z.object({ func: z.literal("sum") }),
  ),
  UniqueAggregation$inboundSchema,
]);
/** @internal */
export type MeterAggregation$Outbound =
  | (PropertyAggregation$Outbound & { func: "avg" })
  | CountAggregation$Outbound
  | (PropertyAggregation$Outbound & { func: "max" })
  | (PropertyAggregation$Outbound & { func: "min" })
  | (PropertyAggregation$Outbound & { func: "sum" })
  | UniqueAggregation$Outbound;

/** @internal */
export const MeterAggregation$outboundSchema: z.ZodMiniType<
  MeterAggregation$Outbound,
  MeterAggregation
> = z.union([
  z.intersection(
    PropertyAggregation$outboundSchema,
    z.object({ func: z.literal("avg") }),
  ),
  CountAggregation$outboundSchema,
  z.intersection(
    PropertyAggregation$outboundSchema,
    z.object({ func: z.literal("max") }),
  ),
  z.intersection(
    PropertyAggregation$outboundSchema,
    z.object({ func: z.literal("min") }),
  ),
  z.intersection(
    PropertyAggregation$outboundSchema,
    z.object({ func: z.literal("sum") }),
  ),
  UniqueAggregation$outboundSchema,
]);

export function meterAggregationToJSON(
  meterAggregation: MeterAggregation,
): string {
  return JSON.stringify(
    MeterAggregation$outboundSchema.parse(meterAggregation),
  );
}
export function meterAggregationFromJSON(
  jsonString: string,
): SafeParseResult<MeterAggregation, SDKValidationError> {
  return safeParse(
    jsonString,
    (x) => MeterAggregation$inboundSchema.parse(JSON.parse(x)),
    `Failed to parse 'MeterAggregation' from JSON`,
  );
}

/** @internal */
export const Meter$inboundSchema: z.ZodMiniType<Meter, unknown> = z.pipe(
  z.object({
    metadata: z.record(z.string(), MetadataOutputType$inboundSchema),
    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))),
    ),
    id: z.string(),
    name: z.string(),
    unit: MeterUnit$inboundSchema,
    custom_label: z.optional(z.nullable(z.string())),
    custom_multiplier: z.optional(z.nullable(z.int())),
    filter: Filter$inboundSchema,
    aggregation: z.union([
      z.intersection(
        PropertyAggregation$inboundSchema,
        z.object({ func: z.literal("avg") }),
      ),
      CountAggregation$inboundSchema,
      z.intersection(
        PropertyAggregation$inboundSchema,
        z.object({ func: z.literal("max") }),
      ),
      z.intersection(
        PropertyAggregation$inboundSchema,
        z.object({ func: z.literal("min") }),
      ),
      z.intersection(
        PropertyAggregation$inboundSchema,
        z.object({ func: z.literal("sum") }),
      ),
      UniqueAggregation$inboundSchema,
    ]),
    organization_id: z.string(),
    archived_at: z.optional(
      z.nullable(z.pipe(
        z.iso.datetime({ offset: true }),
        z.transform(v => new Date(v)),
      )),
    ),
  }),
  z.transform((v) => {
    return remap$(v, {
      "created_at": "createdAt",
      "modified_at": "modifiedAt",
      "custom_label": "customLabel",
      "custom_multiplier": "customMultiplier",
      "organization_id": "organizationId",
      "archived_at": "archivedAt",
    });
  }),
);
/** @internal */
export type Meter$Outbound = {
  metadata: { [k: string]: MetadataOutputType$Outbound };
  created_at: string;
  modified_at: string | null;
  id: string;
  name: string;
  unit: string;
  custom_label?: string | null | undefined;
  custom_multiplier?: number | null | undefined;
  filter: Filter$Outbound;
  aggregation:
    | (PropertyAggregation$Outbound & { func: "avg" })
    | CountAggregation$Outbound
    | (PropertyAggregation$Outbound & { func: "max" })
    | (PropertyAggregation$Outbound & { func: "min" })
    | (PropertyAggregation$Outbound & { func: "sum" })
    | UniqueAggregation$Outbound;
  organization_id: string;
  archived_at?: string | null | undefined;
};

/** @internal */
export const Meter$outboundSchema: z.ZodMiniType<Meter$Outbound, Meter> = z
  .pipe(
    z.object({
      metadata: z.record(z.string(), MetadataOutputType$outboundSchema),
      createdAt: z.pipe(z.date(), z.transform(v => v.toISOString())),
      modifiedAt: z.nullable(
        z.pipe(z.date(), z.transform(v => v.toISOString())),
      ),
      id: z.string(),
      name: z.string(),
      unit: MeterUnit$outboundSchema,
      customLabel: z.optional(z.nullable(z.string())),
      customMultiplier: z.optional(z.nullable(z.int())),
      filter: Filter$outboundSchema,
      aggregation: z.union([
        z.intersection(
          PropertyAggregation$outboundSchema,
          z.object({ func: z.literal("avg") }),
        ),
        CountAggregation$outboundSchema,
        z.intersection(
          PropertyAggregation$outboundSchema,
          z.object({ func: z.literal("max") }),
        ),
        z.intersection(
          PropertyAggregation$outboundSchema,
          z.object({ func: z.literal("min") }),
        ),
        z.intersection(
          PropertyAggregation$outboundSchema,
          z.object({ func: z.literal("sum") }),
        ),
        UniqueAggregation$outboundSchema,
      ]),
      organizationId: z.string(),
      archivedAt: z.optional(
        z.nullable(z.pipe(z.date(), z.transform(v => v.toISOString()))),
      ),
    }),
    z.transform((v) => {
      return remap$(v, {
        createdAt: "created_at",
        modifiedAt: "modified_at",
        customLabel: "custom_label",
        customMultiplier: "custom_multiplier",
        organizationId: "organization_id",
        archivedAt: "archived_at",
      });
    }),
  );

export function meterToJSON(meter: Meter): string {
  return JSON.stringify(Meter$outboundSchema.parse(meter));
}
export function meterFromJSON(
  jsonString: string,
): SafeParseResult<Meter, SDKValidationError> {
  return safeParse(
    jsonString,
    (x) => Meter$inboundSchema.parse(JSON.parse(x)),
    `Failed to parse 'Meter' from JSON`,
  );
}
