/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var flow_surfaces_exports = {};
__export(flow_surfaces_exports, {
  registerFlowSurfacesResource: () => registerFlowSurfacesResource
});
module.exports = __toCommonJS(flow_surfaces_exports);
var import_resourcer = require("@nocobase/resourcer");
var import_constants = require("./constants");
var import_errors = require("./errors");
var import_service = require("./service");
const FLOW_ENGINE_LOCALE_NAMESPACE = "flow-engine";
const FLOW_SURFACE_LOCALE_FALLBACK_NAMESPACES = [
  FLOW_ENGINE_LOCALE_NAMESPACE,
  "@nocobase/flow-engine",
  "@nocobase/plugin-flow-engine",
  "client"
];
const FLOW_SURFACE_LOCAL_TRANSLATIONS = {
  "zh-CN": {
    "Popup for Add New": "\u65B0\u589E\u5F39\u7A97",
    "Popup for Edit": "\u7F16\u8F91\u5F39\u7A97",
    "Popup for Details": "\u8BE6\u60C5\u5F39\u7A97",
    "Auto generated": "\u81EA\u52A8\u751F\u6210",
    'Automatically generated popup template for collection "{{collectionLabel}}" ({{popupLabel}}). Scene: {{scene}}; collection: "{{collectionLabel}}".': "\u4E3A\u6570\u636E\u8868\u201C{{collectionLabel}}\u201D\u81EA\u52A8\u751F\u6210\u7684\u5F39\u7A97\u6A21\u677F\uFF08{{popupLabel}}\uFF09\u3002\u573A\u666F\uFF1A{{scene}}\uFF1B\u6570\u636E\u8868\uFF1A{{collectionLabel}}\u3002",
    'Automatically generated popup template for relation field "{{associationFieldLabel}}" in collection "{{sourceCollectionLabel}}", targeting "{{targetCollectionLabel}}" ({{popupLabel}}). Scene: {{scene}}; source collection: "{{sourceCollectionLabel}}"; association field: "{{associationFieldLabel}}"; target collection: "{{targetCollectionLabel}}".': "\u4E3A\u6570\u636E\u8868\u201C{{sourceCollectionLabel}}\u201D\u4E2D\u7684\u5173\u7CFB\u5B57\u6BB5\u201C{{associationFieldLabel}}\u201D\u81EA\u52A8\u751F\u6210\u7684\u5F39\u7A97\u6A21\u677F\uFF0C\u76EE\u6807\u6570\u636E\u8868\u4E3A\u201C{{targetCollectionLabel}}\u201D\uFF08{{popupLabel}}\uFF09\u3002\u573A\u666F\uFF1A{{scene}}\uFF1B\u6E90\u6570\u636E\u8868\uFF1A{{sourceCollectionLabel}}\uFF1B\u5173\u7CFB\u5B57\u6BB5\uFF1A{{associationFieldLabel}}\uFF1B\u76EE\u6807\u6570\u636E\u8868\uFF1A{{targetCollectionLabel}}\u3002"
  }
};
function getValues(ctx) {
  var _a, _b, _c, _d, _e;
  const values = ((_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) ?? ((_c = ctx.action) == null ? void 0 : _c.params) ?? {};
  const actionName = (_d = ctx.action) == null ? void 0 : _d.actionName;
  if (isInvalidFlowSurfaceWritePayload(values) && actionName && !((_e = import_constants.FLOW_SURFACE_ACTION_DEFINITIONS[actionName]) == null ? void 0 : _e.read)) {
    throw new import_errors.FlowSurfaceBadRequestError(getFlowSurfaceWritePayloadMessage(actionName));
  }
  return values;
}
function isImplicitEmptyValuesBag(value) {
  return !!value && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && Object.keys(value).length === 0;
}
function getRawReadQuery(ctx) {
  var _a;
  const querystring = String(((_a = ctx.request) == null ? void 0 : _a.querystring) ?? "");
  if (!querystring) {
    return {};
  }
  try {
    return (0, import_resourcer.parseQuery)(querystring) || {};
  } catch {
    return {};
  }
}
function hasExplicitQueryWrapper(ctx, key) {
  const query = getRawReadQuery(ctx);
  return Object.prototype.hasOwnProperty.call(query, key);
}
function hasExplicitRequestBody(ctx) {
  var _a;
  const headers = ((_a = ctx.request) == null ? void 0 : _a.headers) ?? {};
  const contentLength = headers["content-length"];
  if (Array.isArray(contentLength)) {
    return contentLength.some((value) => value !== "0");
  }
  if (typeof contentLength === "string") {
    return contentLength !== "0";
  }
  return Boolean(headers["transfer-encoding"]);
}
function getReadValues(ctx) {
  var _a, _b, _c;
  if (((_b = (_a = ctx.request) == null ? void 0 : _a.method) == null ? void 0 : _b.toUpperCase()) !== "GET") {
    (0, import_errors.throwBadRequest)(
      `flowSurfaces:get only supports GET with root query locator fields like /api/flowSurfaces:get?uid=...`
    );
  }
  if (hasExplicitQueryWrapper(ctx, "target")) {
    (0, import_errors.throwBadRequest)(`flowSurfaces:get only accepts root locator fields; do not wrap them in 'target'`);
  }
  if (hasExplicitQueryWrapper(ctx, "values")) {
    (0, import_errors.throwBadRequest)(`flowSurfaces:get only accepts root locator fields; do not wrap them in 'values'`);
  }
  const params = ((_c = ctx.action) == null ? void 0 : _c.params) ?? {};
  if (!Object.prototype.hasOwnProperty.call(params, "values")) {
    return params;
  }
  const values = params.values;
  if (typeof values !== "undefined" && !isImplicitEmptyValuesBag(values)) {
    return params;
  }
  if (hasExplicitRequestBody(ctx)) {
    return params;
  }
  const { values: _values, ...rest } = params;
  return rest;
}
function writeFlowSurfaceErrorResponse(ctx, error) {
  const normalized = (0, import_errors.normalizeFlowSurfaceError)(error);
  ctx.withoutDataWrapping = true;
  ctx.type = "application/json";
  ctx.status = normalized.status;
  ctx.body = normalized.toResponseBody();
}
function isFlowSurfaceWriteActionName(value) {
  return Object.prototype.hasOwnProperty.call(import_constants.FLOW_SURFACE_ACTION_DEFINITIONS, value);
}
function getFlowSurfaceRequestActionName(ctx) {
  var _a, _b;
  const actionName = String(((_a = ctx.action) == null ? void 0 : _a.actionName) || "").trim();
  if (isFlowSurfaceWriteActionName(actionName)) {
    return actionName;
  }
  const path = String(ctx.path || ((_b = ctx.request) == null ? void 0 : _b.path) || "").trim();
  const match = path.match(/(?:^|\/)flowSurfaces:([^/?#]+)$/);
  const rawActionName = String((match == null ? void 0 : match[1]) || "").trim();
  return isFlowSurfaceWriteActionName(rawActionName) ? rawActionName : void 0;
}
function isFlowSurfaceWriteRequest(ctx) {
  var _a;
  if (String(((_a = ctx.request) == null ? void 0 : _a.method) || "").toUpperCase() !== "POST") {
    return false;
  }
  const actionName = getFlowSurfaceRequestActionName(ctx);
  return !!actionName && import_constants.FLOW_SURFACE_ACTION_DEFINITIONS[actionName].read === false;
}
function isInvalidFlowSurfaceWritePayload(value) {
  if (!value || typeof value !== "object") {
    return true;
  }
  return Array.isArray(value);
}
function getFlowSurfaceWritePayloadMessage(actionName) {
  const noun = actionName === "applyBlueprint" || actionName === "applyApprovalBlueprint" ? "payload" : "values";
  return `flowSurfaces ${actionName} ${noun} must be an object`;
}
function isFlowSurfaceWriteBodyParserShapeError(error) {
  const parserError = error;
  return error instanceof SyntaxError && parserError.status === 400 && parserError.message === "invalid JSON, only supports object and array";
}
async function runFlowSurfaceWriteBodyParserErrorWrapper(ctx, next) {
  try {
    await next();
  } catch (error) {
    if (!isFlowSurfaceWriteRequest(ctx) || !isFlowSurfaceWriteBodyParserShapeError(error)) {
      throw error;
    }
    const actionName = getFlowSurfaceRequestActionName(ctx);
    if (!actionName) {
      throw error;
    }
    writeFlowSurfaceErrorResponse(ctx, new import_errors.FlowSurfaceBadRequestError(getFlowSurfaceWritePayloadMessage(actionName)));
  }
}
function isAclPermissionDeniedForFlowSurfaces(ctx, error) {
  var _a, _b;
  const resourceName = ((_a = ctx.action) == null ? void 0 : _a.resourceName) ?? ((_b = ctx.permission) == null ? void 0 : _b.resourceName);
  return resourceName === "flowSurfaces" && (error == null ? void 0 : error.status) === 403 && (error == null ? void 0 : error.message) === "No permissions";
}
function toFlowSurfaceForbiddenError(error) {
  const message = error instanceof Error ? error.message : String(error);
  return new import_errors.FlowSurfaceForbiddenError(message);
}
async function runFlowSurfaceAclErrorWrapper(ctx, next) {
  try {
    await next();
  } catch (error) {
    if (!isAclPermissionDeniedForFlowSurfaces(ctx, error)) {
      throw error;
    }
    writeFlowSurfaceErrorResponse(ctx, toFlowSurfaceForbiddenError(error));
  }
}
async function runFlowSurfaceAction(ctx, next, handler) {
  try {
    ctx.body = await handler();
    await next();
  } catch (error) {
    writeFlowSurfaceErrorResponse(ctx, error);
    await next();
  }
}
function invokeFlowSurfaceServiceAction(service, actionName, values, options = {}) {
  const handler = service[actionName];
  return handler.call(service, values, options);
}
function interpolateTranslation(value, options) {
  return value.replace(/\{\{\s*([^}\s]+)\s*\}\}/g, (_match, name) => {
    const replacement = options == null ? void 0 : options[name];
    return replacement === null || typeof replacement === "undefined" ? "" : String(replacement);
  });
}
function getResourceTranslation(ctx, key, options) {
  var _a, _b, _c, _d;
  const locale = ((_a = ctx.getCurrentLocale) == null ? void 0 : _a.call(ctx)) || ((_b = ctx.i18n) == null ? void 0 : _b.language);
  const i18n = (_c = ctx.app) == null ? void 0 : _c.i18n;
  if (!locale || !i18n) {
    return void 0;
  }
  for (const ns of FLOW_SURFACE_LOCALE_FALLBACK_NAMESPACES) {
    const value = (_d = i18n.getResource) == null ? void 0 : _d.call(i18n, locale, ns, key);
    if (typeof value === "string") {
      return interpolateTranslation(value, options);
    }
  }
  return void 0;
}
function getLocalTranslation(ctx, key, options) {
  var _a, _b;
  const locale = String(((_a = ctx.getCurrentLocale) == null ? void 0 : _a.call(ctx)) || ((_b = ctx.i18n) == null ? void 0 : _b.language) || "").trim();
  const resources = FLOW_SURFACE_LOCAL_TRANSLATIONS[locale];
  const value = resources == null ? void 0 : resources[key];
  return typeof value === "string" ? interpolateTranslation(value, options) : void 0;
}
function getFlowSurfaceTranslate(ctx) {
  var _a, _b, _c;
  const translate = ((_b = (_a = ctx.i18n) == null ? void 0 : _a.t) == null ? void 0 : _b.bind(ctx.i18n)) || ((_c = ctx.t) == null ? void 0 : _c.bind(ctx));
  if (typeof translate !== "function") {
    return void 0;
  }
  return (key, options) => {
    const resourceValue = getResourceTranslation(ctx, key, options);
    if (typeof resourceValue === "string") {
      return resourceValue;
    }
    const localValue = getLocalTranslation(ctx, key, options);
    if (typeof localValue === "string") {
      return localValue;
    }
    return translate(key, {
      ns: [FLOW_ENGINE_LOCALE_NAMESPACE, "client"],
      nsMode: "fallback",
      ...options || {}
    });
  };
}
function registerFlowSurfacesResource(plugin) {
  const service = new import_service.FlowSurfacesService(plugin);
  const actions = Object.fromEntries(
    import_constants.FLOW_SURFACES_ACTION_NAMES.map((actionName) => [
      actionName,
      async (ctx, next) => {
        await runFlowSurfaceAction(ctx, next, async () => {
          var _a;
          const definition = import_constants.FLOW_SURFACE_ACTION_DEFINITIONS[actionName];
          const values = definition.valueSource === "read" ? getReadValues(ctx) : getValues(ctx);
          const t = getFlowSurfaceTranslate(ctx);
          const currentRoles = (_a = ctx.state) == null ? void 0 : _a.currentRoles;
          if (definition.transaction) {
            return service.transaction(
              (transaction) => invokeFlowSurfaceServiceAction(service, actionName, values, { transaction, currentRoles, t })
            );
          }
          return invokeFlowSurfaceServiceAction(service, actionName, values, { currentRoles, t });
        });
      }
    ])
  );
  plugin.app.acl.registerSnippet({
    name: "ui.flowSurfaces",
    actions: ["flowSurfaces:*"]
  });
  plugin.app.acl.allow("flowSurfaces", [...import_constants.FLOW_SURFACES_READ_ACTION_NAMES], "loggedIn");
  plugin.app.acl.use(runFlowSurfaceAclErrorWrapper, {
    tag: "flow-surfaces-acl-errors",
    after: "allow-manager",
    before: "core"
  });
  plugin.app.use(runFlowSurfaceWriteBodyParserErrorWrapper, {
    tag: "flow-surfaces-write-body-errors",
    before: "bodyParser"
  });
  plugin.app.resourceManager.define({
    name: "flowSurfaces",
    actions
  });
  return service;
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  registerFlowSurfacesResource
});
