import { z } from "zod";
import { PRODUCT_ANALYTICS_EVENT_NAMES } from "@app/shared-types";

export const MAX_ANALYTICS_BATCH_SIZE = 50;
export const MAX_ANALYTICS_PROPERTY_SIZE = 8 * 1024; // 8 KiB per event properties JSON

const eventNameSchema = z.enum(PRODUCT_ANALYTICS_EVENT_NAMES);

const analyticsEventSchema = z.object({
  name: eventNameSchema,
  occurredAt: z.string().refine((v) => !Number.isNaN(Date.parse(v))).optional(),
  anonymousId: z.string().max(64).optional(),
  sessionId: z.string().max(64).optional(),
  householdId: z.string().uuid().optional(),
  appVersion: z.string().max(32).optional(),
  platform: z.enum(["ios", "android", "web"]).optional(),
  locale: z.string().max(16).optional(),
  experimentVariant: z.string().max(128).optional(),
  properties: z.record(z.string(), z.unknown()).default({}),
});

export const analyticsBatchInputSchema = z.object({
  events: z
    .array(analyticsEventSchema)
    .min(1, "At least one event is required")
    .max(MAX_ANALYTICS_BATCH_SIZE, `Max ${MAX_ANALYTICS_BATCH_SIZE} events per batch`),
});

export type AnalyticsBatchInput = z.infer<typeof analyticsBatchInputSchema>;

/**
 * Validate that the JSON-stringified properties of each event fit within the
 * per-event byte budget. Call this after zod parsing.
 */
export function validateAnalyticsPropertySize(events: AnalyticsBatchInput["events"]): void {
  for (let i = 0; i < events.length; i++) {
    const size = new Blob([JSON.stringify(events[i]?.properties ?? {})]).size;
    if (size > MAX_ANALYTICS_PROPERTY_SIZE) {
      throw new Error(
        `Event ${i} properties exceed ${MAX_ANALYTICS_PROPERTY_SIZE} bytes (${size})`,
      );
    }
  }
}
