import { assert } from "../../../shared/src/asserts.js";
import { jsonSchema } from "../../../shared/src/json-schema.js";
import { readonlyObject } from "../../../shared/src/valita.js";
import { commitIsLocalDD31, DEFAULT_HEAD_NAME, localMutations } from "../db/commit.js";
import { PushError, assertPusherResult } from "../pusher.js";
import { ReportError } from "../report-error.js";
import { toError } from "../to-error.js";
import { withRead } from "../with-transactions.js";
import { clientIDSchema, clientGroupIDSchema } from "./ids.js";
import { number, string, object, array, literal } from "@badrap/valita";
const PUSH_VERSION_DD31 = 1;
const mutationV1Schema = readonlyObject({
  id: number(),
  name: string(),
  args: jsonSchema,
  timestamp: number(),
  clientID: clientIDSchema
});
object({
  pushVersion: literal(1),
  schemaVersion: string(),
  profileID: string(),
  clientGroupID: clientGroupIDSchema,
  mutations: array(mutationV1Schema)
});
function convertDD31(lm) {
  return {
    id: lm.mutationID,
    name: lm.mutatorName,
    args: lm.mutatorArgsJSON,
    timestamp: lm.timestamp,
    clientID: lm.clientID
  };
}
async function push(requestID, store, lc, profileID, clientGroupID, _clientID, pusher, schemaVersion, pushVersion) {
  const pending = await withRead(store, async (dagRead) => {
    const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);
    if (!mainHeadHash) {
      throw new Error("Internal no main head");
    }
    return localMutations(mainHeadHash, dagRead);
  });
  if (pending.length === 0) {
    return void 0;
  }
  pending.reverse();
  assert(pushVersion === PUSH_VERSION_DD31);
  const pushMutations = [];
  for (const commit of pending) {
    if (commitIsLocalDD31(commit)) {
      pushMutations.push(convertDD31(commit.meta));
    } else {
      throw new Error("Internal non local pending commit");
    }
  }
  assert(clientGroupID);
  const pushReq = {
    profileID,
    clientGroupID,
    mutations: pushMutations,
    pushVersion: PUSH_VERSION_DD31,
    schemaVersion
  };
  lc.debug?.("Starting push...");
  const pushStart = Date.now();
  const pusherResult = await callPusher(pusher, pushReq, requestID);
  lc.debug?.("...Push complete in ", Date.now() - pushStart, "ms");
  return pusherResult;
}
async function callPusher(pusher, body, requestID) {
  let pusherResult;
  try {
    pusherResult = await pusher(body, requestID);
  } catch (e) {
    throw new PushError(toError(e));
  }
  try {
    assertPusherResult(pusherResult);
    return pusherResult;
  } catch (e) {
    throw new ReportError("Invalid pusher result", toError(e));
  }
}
export {
  PUSH_VERSION_DD31,
  push
};
//# sourceMappingURL=push.js.map
