import { jsonSchema } from "../../shared/src/json-schema.js";
import "../../shared/src/valita.js";
import { rowSchema } from "./data.js";
import { pushFailedBodySchema } from "./error.js";
import { mutationIDSchema } from "./mutation-id.js";
import { CRUD, Custom } from "./mutation-type-enum.js";
import { primaryKeySchema, primaryKeyValueRecordSchema } from "./primary-key.js";
import { union, object, number, string, literal, tuple, array } from "@badrap/valita";
const CRUD_MUTATION_NAME = "_zero_crud";
const CLEANUP_RESULTS_MUTATION_NAME = "_zero_cleanupResults";
const cleanupResultsArgSchema = union(
  // Legacy format (no type field) - treat as single
  object({
    clientGroupID: string(),
    clientID: string(),
    upToMutationID: number()
  }),
  // Explicit single: delete up to a specific mutation ID for one client
  object({
    type: literal("single"),
    clientGroupID: string(),
    clientID: string(),
    upToMutationID: number()
  }),
  // Bulk: delete all mutations for multiple clients
  object({
    type: literal("bulk"),
    clientGroupID: string(),
    clientIDs: tuple([string()]).concat(array(string()))
  })
);
const insertOpSchema = object({
  op: literal("insert"),
  tableName: string(),
  primaryKey: primaryKeySchema,
  value: rowSchema
});
const upsertOpSchema = object({
  op: literal("upsert"),
  tableName: string(),
  primaryKey: primaryKeySchema,
  value: rowSchema
});
const updateOpSchema = object({
  op: literal("update"),
  tableName: string(),
  primaryKey: primaryKeySchema,
  // Partial value with at least the primary key fields
  value: rowSchema
});
const deleteOpSchema = object({
  op: literal("delete"),
  tableName: string(),
  primaryKey: primaryKeySchema,
  // Partial value representing the primary key
  value: primaryKeyValueRecordSchema
});
const crudOpSchema = union(
  insertOpSchema,
  upsertOpSchema,
  updateOpSchema,
  deleteOpSchema
);
const crudArgSchema = object({
  ops: array(crudOpSchema)
});
const crudArgsSchema = tuple([crudArgSchema]);
const crudMutationSchema = object({
  type: literal(CRUD),
  id: number(),
  clientID: string(),
  name: literal(CRUD_MUTATION_NAME),
  args: crudArgsSchema,
  timestamp: number()
});
const customMutationSchema = object({
  type: literal(Custom),
  id: number(),
  clientID: string(),
  name: string(),
  args: array(jsonSchema),
  timestamp: number()
});
const mutationSchema = union(crudMutationSchema, customMutationSchema);
const pushBodySchema = object({
  clientGroupID: string(),
  mutations: array(mutationSchema),
  pushVersion: number(),
  // For legacy (CRUD) mutations, the schema is tied to the client group /
  // sync connection. For custom mutations, schema versioning is delegated
  // to the custom protocol / api-server.
  schemaVersion: number().optional(),
  timestamp: number(),
  requestID: string(),
  /**
   * @deprecated auth is managed at client-group scope via connect/updateAuth
   * and should not be included in push messages.
   */
  auth: string().optional()
});
const pushMessageSchema = tuple([literal("push"), pushBodySchema]);
const appErrorSchema = object({
  error: literal("app"),
  // The user can return any additional data here
  message: string().optional(),
  details: jsonSchema.optional()
});
const zeroErrorSchema = object({
  error: union(
    /** @deprecated push oooMutation errors are now represented as ['error', { ... }] messages */
    literal("oooMutation"),
    literal("alreadyProcessed")
  ),
  details: jsonSchema.optional()
});
const mutationOkSchema = object({
  // The user can return any additional data here
  data: jsonSchema.optional()
});
const mutationErrorSchema = union(appErrorSchema, zeroErrorSchema);
const mutationResultSchema = union(
  mutationOkSchema,
  mutationErrorSchema
);
const mutationResponseSchema = object({
  id: mutationIDSchema,
  result: mutationResultSchema
});
const pushOkSchema = object({
  mutations: array(mutationResponseSchema)
});
const unsupportedPushVersionSchema = object({
  /** @deprecated */
  error: literal("unsupportedPushVersion"),
  /** @deprecated */
  mutationIDs: array(mutationIDSchema).optional()
});
const unsupportedSchemaVersionSchema = object({
  /** @deprecated */
  error: literal("unsupportedSchemaVersion"),
  /** @deprecated */
  mutationIDs: array(mutationIDSchema).optional()
});
const httpErrorSchema = object({
  /** @deprecated */
  error: literal("http"),
  /** @deprecated */
  status: number(),
  /** @deprecated */
  details: string(),
  /** @deprecated */
  mutationIDs: array(mutationIDSchema).optional()
});
const zeroPusherErrorSchema = object({
  /** @deprecated */
  error: literal("zeroPusher"),
  /** @deprecated */
  details: string(),
  /** @deprecated */
  mutationIDs: array(mutationIDSchema).optional()
});
const pushErrorSchema = union(
  unsupportedPushVersionSchema,
  unsupportedSchemaVersionSchema,
  httpErrorSchema,
  zeroPusherErrorSchema
);
const pushResponseBodySchema = union(pushOkSchema, pushErrorSchema);
const pushResponseSchema = union(
  pushResponseBodySchema,
  pushFailedBodySchema
);
const pushResponseMessageSchema = tuple([
  literal("pushResponse"),
  pushResponseBodySchema
]);
const ackMutationResponsesMessageSchema = tuple([
  literal("ackMutationResponses"),
  mutationIDSchema
]);
const pushParamsSchema = object({
  schema: string(),
  appID: string()
});
function mapCRUD(arg, map) {
  return {
    ops: arg.ops.map(
      ({ op, tableName, primaryKey, value }) => ({
        op,
        tableName: map.tableName(tableName),
        primaryKey: map.columns(tableName, primaryKey),
        value: map.row(tableName, value)
        // The cast is necessary because ts objects to the `value` field
        // for "delete" ops being different.
      })
    )
  };
}
export {
  CLEANUP_RESULTS_MUTATION_NAME,
  CRUD_MUTATION_NAME,
  ackMutationResponsesMessageSchema,
  cleanupResultsArgSchema,
  crudMutationSchema,
  customMutationSchema,
  mapCRUD,
  mutationResponseSchema,
  mutationResultSchema,
  mutationSchema,
  pushBodySchema,
  pushMessageSchema,
  pushParamsSchema,
  pushResponseBodySchema,
  pushResponseMessageSchema,
  pushResponseSchema
};
//# sourceMappingURL=push.js.map
