import { getErrorMessage, getErrorDetails } from "../../../shared/src/error.js";
import { parse } from "../../../shared/src/valita.js";
import { mapAST } from "../../../zero-protocol/src/ast.js";
import { transformRequestMessageSchema } from "../../../zero-protocol/src/custom-queries.js";
import { TransformFailed } from "../../../zero-protocol/src/error-kind-enum.js";
import { Server } from "../../../zero-protocol/src/error-origin-enum.js";
import { Parse, Internal } from "../../../zero-protocol/src/error-reason-enum.js";
import { clientToServer } from "../../../zero-schema/src/name-mapper.js";
import { QueryParseError } from "../../../zql/src/query/error.js";
import { asQueryInternals } from "../../../zql/src/query/query-internals.js";
import { createLogContext } from "../logging.js";
function handleGetQueriesRequest(cb, schema, requestOrJsonBody, logLevel = "info") {
  return transform(cb, schema, requestOrJsonBody, "getQueries", logLevel);
}
function handleTransformRequest(cb, schema, requestOrJsonBody, logLevel = "info") {
  return transform(cb, schema, requestOrJsonBody, "transform", logLevel);
}
function handleQueryRequest(transformQuery, schema, requestOrJsonBody, logLevel = "info") {
  return transform(
    (name, argsArray) => transformQuery(name, argsArray[0]),
    schema,
    requestOrJsonBody,
    "query",
    logLevel
  );
}
async function transform(cb, schema, requestOrJsonBody, apiName, logLevel = "info") {
  const lc = createLogContext(logLevel).withContext("TransformRequest");
  let parsed;
  let queryIDs = [];
  try {
    let body;
    if (requestOrJsonBody instanceof Request) {
      body = await requestOrJsonBody.json();
    } else {
      body = requestOrJsonBody;
    }
    parsed = parse(body, transformRequestMessageSchema);
    queryIDs = parsed[1].map((r) => r.id);
  } catch (error) {
    lc.error?.(`Failed to parse ${apiName} request`, error);
    const message = `Failed to parse ${apiName} request: ${getErrorMessage(error)}`;
    const details = getErrorDetails(error);
    return [
      "transformFailed",
      {
        kind: TransformFailed,
        origin: Server,
        reason: Parse,
        message,
        queryIDs,
        ...details ? { details } : {}
      }
    ];
  }
  try {
    const nameMapper = clientToServer(schema.tables);
    const responses = await Promise.all(
      parsed[1].map(async (req) => {
        let finalQuery;
        try {
          const result = await cb(req.name, req.args);
          finalQuery = "query" in result ? result.query : result;
        } catch (error) {
          const message = getErrorMessage(error);
          const details = getErrorDetails(error);
          return {
            error: error instanceof QueryParseError ? "parse" : "app",
            id: req.id,
            name: req.name,
            message,
            ...details ? { details } : {}
          };
        }
        try {
          const q = asQueryInternals(finalQuery);
          const ast = mapAST(q.ast, nameMapper);
          return {
            id: req.id,
            name: req.name,
            ast
          };
        } catch (error) {
          lc.error?.("Failed to map AST", error);
          throw error;
        }
      })
    );
    return ["transformed", responses];
  } catch (e) {
    const message = getErrorMessage(e);
    const details = getErrorDetails(e);
    return [
      "transformFailed",
      {
        kind: TransformFailed,
        origin: Server,
        reason: Internal,
        message,
        queryIDs,
        ...details ? { details } : {}
      }
    ];
  }
}
export {
  handleGetQueriesRequest,
  handleQueryRequest,
  handleTransformRequest
};
//# sourceMappingURL=process-queries.js.map
