/**
 * 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 __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var linkage_exports = {};
__export(linkage_exports, {
  buildReactionFingerprint: () => buildReactionFingerprint,
  compileActionLinkageCanonicalRules: () => compileActionLinkageCanonicalRules,
  compileBlockLinkageCanonicalRules: () => compileBlockLinkageCanonicalRules,
  compileFieldLinkageCanonicalRules: () => compileFieldLinkageCanonicalRules,
  normalizeActionLinkageRules: () => normalizeActionLinkageRules,
  normalizeBlockLinkageRules: () => normalizeBlockLinkageRules,
  normalizeFieldLinkageRules: () => normalizeFieldLinkageRules,
  validateActionLinkageRulesAgainstCapability: () => validateActionLinkageRulesAgainstCapability,
  validateActionLinkageSceneSupport: () => validateActionLinkageSceneSupport,
  validateBlockLinkageRulesAgainstCapability: () => validateBlockLinkageRulesAgainstCapability,
  validateBlockLinkageSceneSupport: () => validateBlockLinkageSceneSupport,
  validateFieldLinkageRulesAgainstCapability: () => validateFieldLinkageRulesAgainstCapability,
  validateFieldLinkageSceneSupport: () => validateFieldLinkageSceneSupport,
  validateReactionFilterAgainstCapability: () => validateReactionFilterAgainstCapability
});
module.exports = __toCommonJS(linkage_exports);
var import_node_crypto = require("node:crypto");
var import_lodash = __toESM(require("lodash"));
var import_context = require("../context");
var import_errors = require("../errors");
var import_filter_group = require("../filter-group");
var import_errors2 = require("./errors");
var import_registry = require("./registry");
const EMPTY_FILTER = {
  logic: "$and",
  items: []
};
const CONTEXT_EXPR_RE = /^\{\{\s*ctx(?:\.([^}]+?))?\s*\}\}$/;
const CTX_PREFIX_RE = /^ctx\./;
function buildStableFingerprintString(value) {
  if (import_lodash.default.isNil(value)) {
    return "null";
  }
  if (Array.isArray(value)) {
    return `[${value.map((item) => buildStableFingerprintString(item)).join(",")}]`;
  }
  if (import_lodash.default.isPlainObject(value)) {
    const entries = Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${buildStableFingerprintString(value[key])}`);
    return `{${entries.join(",")}}`;
  }
  return JSON.stringify(value);
}
function assertRuleArray(rules, label) {
  if (!Array.isArray(rules)) {
    (0, import_errors.throwBadRequest)(`${label} must be an array.`);
  }
}
function normalizeKey(rawKey, fallbackPrefix, index) {
  const trimmed = typeof rawKey === "string" ? rawKey.trim() : "";
  return trimmed || `${fallbackPrefix}-${index + 1}`;
}
function normalizeTitle(rawTitle, index) {
  const trimmed = typeof rawTitle === "string" ? rawTitle.trim() : "";
  return trimmed || `Linkage rule ${index + 1}`;
}
function normalizeBoolean(rawValue, fallback = true) {
  return typeof rawValue === "boolean" ? rawValue : fallback;
}
function extractBareContextPath(rawPath, fieldName = "condition.path") {
  var _a;
  if (typeof rawPath !== "string" || !rawPath.trim()) {
    (0, import_errors.throwBadRequest)(`${fieldName} must be a non-empty string.`, import_errors2.FLOW_SURFACE_REACTION_INVALID_CONDITION_PATH);
  }
  const trimmed = rawPath.trim();
  const templateMatch = trimmed.match(CONTEXT_EXPR_RE);
  const bare = ((_a = templateMatch == null ? void 0 : templateMatch[1]) == null ? void 0 : _a.trim()) || (trimmed.startsWith("ctx.") ? trimmed.replace(CTX_PREFIX_RE, "") : trimmed);
  if (!bare || !(0, import_context.isBareFlowContextPath)(bare)) {
    (0, import_errors.throwBadRequest)(
      `${fieldName} must be a bare flow context path such as "record.id".`,
      import_errors2.FLOW_SURFACE_REACTION_INVALID_CONDITION_PATH
    );
  }
  return bare;
}
function formatContextPath(path) {
  return `{{ ctx.${path} }}`;
}
function clonePlain(value) {
  return import_lodash.default.cloneDeep(value);
}
function normalizeFilterValue(value) {
  if (import_lodash.default.isPlainObject(value) && value.source === "path" && typeof value.path === "string") {
    return {
      ...value,
      path: extractBareContextPath(value.path, "condition.value.path")
    };
  }
  if (Array.isArray(value)) {
    return value.map((item) => normalizeFilterValue(item));
  }
  if (import_lodash.default.isPlainObject(value)) {
    return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, normalizeFilterValue(item)]));
  }
  return clonePlain(value);
}
function compileFilterValue(value) {
  if (import_lodash.default.isPlainObject(value) && value.source === "path" && typeof value.path === "string") {
    return formatContextPath(extractBareContextPath(value.path, "condition.value.path"));
  }
  if (Array.isArray(value)) {
    return value.map((item) => compileFilterValue(item));
  }
  if (import_lodash.default.isPlainObject(value)) {
    return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, compileFilterValue(item)]));
  }
  return clonePlain(value);
}
function normalizeReactionFilter(rawFilter) {
  if (!rawFilter || !import_lodash.default.isPlainObject(rawFilter)) {
    return clonePlain(EMPTY_FILTER);
  }
  const normalizedFilter = (0, import_filter_group.normalizeFlowSurfaceCompatibleFilterGroupValue)(
    rawFilter,
    "flowSurfaces linkage rule condition",
    {
      allowContextPathValue: true
    }
  );
  const visit = (node) => {
    if (!import_lodash.default.isPlainObject(node)) {
      return node;
    }
    if (Array.isArray(node.items)) {
      return {
        ...Object.fromEntries(Object.entries(node).filter(([key]) => key !== "items")),
        items: node.items.map((item) => visit(item))
      };
    }
    const next = { ...node };
    if ("path" in next) {
      next.path = extractBareContextPath(next.path);
    }
    if ("value" in next) {
      next.value = normalizeFilterValue(next.value);
    }
    return next;
  };
  return visit(normalizedFilter);
}
function compileReactionFilter(filter) {
  const visit = (node) => {
    if (!import_lodash.default.isPlainObject(node)) {
      return clonePlain(node);
    }
    if (Array.isArray(node.items)) {
      return {
        ...Object.fromEntries(Object.entries(node).filter(([key]) => key !== "items")),
        items: node.items.map((item) => visit(item))
      };
    }
    const next = { ...node };
    if ("path" in next && typeof next.path === "string") {
      next.path = formatContextPath(extractBareContextPath(next.path));
    }
    if ("value" in next) {
      next.value = compileFilterValue(next.value);
    }
    return next;
  };
  return visit(filter);
}
function isRunJsExpr(value) {
  if (!import_lodash.default.isPlainObject(value)) {
    return false;
  }
  const keys = Object.keys(value);
  if (!keys.includes("code")) {
    return false;
  }
  if (typeof value.code !== "string") {
    return false;
  }
  if ("version" in value && value.version != null && value.version !== "v1" && value.version !== "v2") {
    return false;
  }
  return keys.every((key) => key === "code" || key === "version");
}
function normalizeValueExpr(value) {
  if (import_lodash.default.isPlainObject(value) && value.source === "literal") {
    return {
      source: "literal",
      value: clonePlain(value.value)
    };
  }
  if (import_lodash.default.isPlainObject(value) && value.source === "path") {
    return {
      source: "path",
      path: extractBareContextPath(value.path, "value.path")
    };
  }
  if (import_lodash.default.isPlainObject(value) && value.source === "runjs") {
    if (typeof value.code !== "string") {
      (0, import_errors.throwBadRequest)("runjs value.code must be a string.");
    }
    return {
      source: "runjs",
      code: value.code,
      ...value.version ? { version: value.version } : {}
    };
  }
  if (import_lodash.default.isPlainObject(value) && "source" in value) {
    (0, import_errors.throwBadRequest)(
      `value.source "${String(value.source)}" is not supported. Expected one of "literal", "path", or "runjs".`,
      import_errors2.FLOW_SURFACE_REACTION_INVALID_VALUE_SOURCE
    );
  }
  if (isRunJsExpr(value)) {
    return {
      source: "runjs",
      code: value.code,
      ...value.version ? { version: value.version } : {}
    };
  }
  if (typeof value === "string") {
    const templateMatch = value.trim().match(CONTEXT_EXPR_RE);
    if (templateMatch == null ? void 0 : templateMatch[1]) {
      return {
        source: "path",
        path: extractBareContextPath(value, "value")
      };
    }
  }
  return {
    source: "literal",
    value: clonePlain(value)
  };
}
function compileValueExpr(value) {
  if ((value == null ? void 0 : value.source) === "path") {
    return formatContextPath(extractBareContextPath(value.path, "value.path"));
  }
  if ((value == null ? void 0 : value.source) === "runjs") {
    if (typeof value.code !== "string") {
      (0, import_errors.throwBadRequest)("runjs value.code must be a string.");
    }
    return {
      code: value.code,
      ...value.version ? { version: value.version } : {}
    };
  }
  return clonePlain(value == null ? void 0 : value.value);
}
function normalizeFieldPath(rawPath, fieldName) {
  if (typeof rawPath !== "string" || !rawPath.trim()) {
    (0, import_errors.throwBadRequest)(`${fieldName} must be a non-empty string.`);
  }
  return rawPath.trim();
}
function normalizeFieldPaths(rawPaths, fieldName) {
  if (!Array.isArray(rawPaths)) {
    (0, import_errors.throwBadRequest)(`${fieldName} must be an array of field paths.`);
  }
  return import_lodash.default.uniq(rawPaths.map((path, index) => normalizeFieldPath(path, `${fieldName}[${index}]`))).filter(Boolean);
}
function normalizeAssignItem(rawItem, index, prefix, fallbackMode) {
  const rawTargetPath = (rawItem == null ? void 0 : rawItem.targetPath) ?? (typeof (rawItem == null ? void 0 : rawItem.field) === "string" || typeof (rawItem == null ? void 0 : rawItem.field) === "number" ? String(rawItem.field) : void 0);
  const rawValue = "value" in (rawItem || {}) ? rawItem.value : fallbackMode === "default" ? rawItem == null ? void 0 : rawItem.initialValue : rawItem == null ? void 0 : rawItem.assignValue;
  return {
    key: normalizeKey(rawItem == null ? void 0 : rawItem.key, prefix, index),
    enabled: normalizeBoolean((rawItem == null ? void 0 : rawItem.enabled) ?? (rawItem == null ? void 0 : rawItem.enable), true),
    targetPath: normalizeFieldPath(rawTargetPath, `${prefix}[${index}].targetPath`),
    when: normalizeReactionFilter((rawItem == null ? void 0 : rawItem.when) ?? (rawItem == null ? void 0 : rawItem.condition)),
    value: normalizeValueExpr(rawValue)
  };
}
function normalizeRuleCommon(rawRule, index, prefix) {
  return {
    key: normalizeKey(rawRule == null ? void 0 : rawRule.key, prefix, index),
    title: normalizeTitle(rawRule == null ? void 0 : rawRule.title, index),
    enabled: normalizeBoolean((rawRule == null ? void 0 : rawRule.enabled) ?? (rawRule == null ? void 0 : rawRule.enable), true),
    when: normalizeReactionFilter((rawRule == null ? void 0 : rawRule.when) ?? (rawRule == null ? void 0 : rawRule.condition))
  };
}
function normalizeBlockAction(rawAction, index, prefix) {
  var _a, _b, _c, _d, _e, _f;
  const type = rawAction == null ? void 0 : rawAction.type;
  if (type === "setBlockState") {
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type,
      state: rawAction == null ? void 0 : rawAction.state
    };
  }
  if (type === "runjs") {
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type,
      code: String((rawAction == null ? void 0 : rawAction.code) ?? ""),
      ...(rawAction == null ? void 0 : rawAction.version) ? { version: rawAction.version } : {}
    };
  }
  switch (rawAction == null ? void 0 : rawAction.name) {
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.block.setBlockState:
      return {
        key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
        type: "setBlockState",
        state: (_a = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _a.value
      };
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.block.runjs:
    case "runjs":
      return {
        key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
        type: "runjs",
        code: String(((_c = (_b = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _b.value) == null ? void 0 : _c.script) ?? ((_d = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _d.code) ?? ""),
        ...((_f = (_e = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _e.value) == null ? void 0 : _f.version) ? { version: rawAction.params.value.version } : {}
      };
    default:
      (0, import_errors.throwBadRequest)(`Unsupported block linkage action "${String((rawAction == null ? void 0 : rawAction.name) ?? (rawAction == null ? void 0 : rawAction.type) ?? "")}".`);
  }
}
function normalizeActionAction(rawAction, index, prefix) {
  var _a, _b, _c, _d, _e, _f;
  const type = rawAction == null ? void 0 : rawAction.type;
  if (type === "setActionState") {
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type,
      state: rawAction == null ? void 0 : rawAction.state
    };
  }
  if (type === "runjs") {
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type,
      code: String((rawAction == null ? void 0 : rawAction.code) ?? ""),
      ...(rawAction == null ? void 0 : rawAction.version) ? { version: rawAction.version } : {}
    };
  }
  switch (rawAction == null ? void 0 : rawAction.name) {
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.action.setActionState:
      return {
        key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
        type: "setActionState",
        state: (_a = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _a.value
      };
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.action.runjs:
    case "runjs":
      return {
        key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
        type: "runjs",
        code: String(((_c = (_b = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _b.value) == null ? void 0 : _c.script) ?? ((_d = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _d.code) ?? ""),
        ...((_f = (_e = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _e.value) == null ? void 0 : _f.version) ? { version: rawAction.params.value.version } : {}
      };
    default:
      (0, import_errors.throwBadRequest)(`Unsupported action linkage action "${String((rawAction == null ? void 0 : rawAction.name) ?? (rawAction == null ? void 0 : rawAction.type) ?? "")}".`);
  }
}
function normalizeFieldStateAction(rawAction, index, prefix, resolveFieldPath) {
  var _a, _b, _c, _d;
  if ((rawAction == null ? void 0 : rawAction.type) === "setFieldState") {
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type: "setFieldState",
      fieldPaths: normalizeFieldPaths(rawAction == null ? void 0 : rawAction.fieldPaths, `${prefix}[${index}].fieldPaths`),
      state: rawAction == null ? void 0 : rawAction.state
    };
  }
  const rawFields = (_b = (_a = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _a.value) == null ? void 0 : _b.fields;
  return {
    key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
    type: "setFieldState",
    fieldPaths: normalizeFieldPaths(rawFields, `${prefix}[${index}].fieldPaths`).map(
      (fieldUid) => (resolveFieldPath == null ? void 0 : resolveFieldPath(fieldUid)) || fieldUid
    ),
    state: (_d = (_c = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _c.value) == null ? void 0 : _d.state
  };
}
function normalizeFieldAssignAction(rawAction, index, prefix, fallbackMode) {
  var _a;
  if ((rawAction == null ? void 0 : rawAction.type) === "assignField" || (rawAction == null ? void 0 : rawAction.type) === "setFieldDefaultValue") {
    const nextType = fallbackMode === "default" || (rawAction == null ? void 0 : rawAction.type) === "setFieldDefaultValue" ? "setFieldDefaultValue" : "assignField";
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type: nextType,
      items: Array.isArray(rawAction == null ? void 0 : rawAction.items) ? rawAction.items.map(
        (item, itemIndex) => normalizeAssignItem(item, itemIndex, `${prefix}-${index + 1}-item`, fallbackMode)
      ) : []
    };
  }
  const rawValue = (_a = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _a.value;
  const items = Array.isArray(rawValue) ? rawValue.map(
    (item, itemIndex) => normalizeAssignItem(item, itemIndex, `${prefix}-${index + 1}-item`, fallbackMode)
  ) : rawValue && typeof rawValue === "object" ? [normalizeAssignItem(rawValue, 0, `${prefix}-${index + 1}-item`, fallbackMode)] : [];
  return {
    key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
    type: fallbackMode === "default" ? "setFieldDefaultValue" : "assignField",
    items
  };
}
function normalizeFieldRunJsAction(rawAction, index, prefix) {
  var _a, _b, _c, _d, _e;
  if ((rawAction == null ? void 0 : rawAction.type) === "runjs") {
    return {
      key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
      type: "runjs",
      code: String((rawAction == null ? void 0 : rawAction.code) ?? ""),
      ...(rawAction == null ? void 0 : rawAction.version) ? { version: rawAction.version } : {}
    };
  }
  return {
    key: normalizeKey(rawAction == null ? void 0 : rawAction.key, prefix, index),
    type: "runjs",
    code: String(((_b = (_a = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _a.value) == null ? void 0 : _b.script) ?? ((_c = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _c.code) ?? ""),
    ...((_e = (_d = rawAction == null ? void 0 : rawAction.params) == null ? void 0 : _d.value) == null ? void 0 : _e.version) ? { version: rawAction.params.value.version } : {}
  };
}
function normalizeFieldAction(rawAction, index, prefix, options) {
  switch (rawAction == null ? void 0 : rawAction.type) {
    case "setFieldState":
      return normalizeFieldStateAction(rawAction, index, prefix, options.resolveFieldPath);
    case "assignField":
    case "setFieldDefaultValue":
      return normalizeFieldAssignAction(
        rawAction,
        index,
        prefix,
        rawAction.type === "setFieldDefaultValue" ? "default" : "assign"
      );
    case "runjs":
      return normalizeFieldRunJsAction(rawAction, index, prefix);
    default:
      break;
  }
  switch (rawAction == null ? void 0 : rawAction.name) {
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.form.setFieldState:
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.details.setFieldState:
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.subForm.setFieldState:
      return normalizeFieldStateAction(rawAction, index, prefix, options.resolveFieldPath);
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.form.assignField:
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.subForm.assignField:
      return normalizeFieldAssignAction(rawAction, index, prefix, "assign");
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.form.setFieldDefaultValue:
      return normalizeFieldAssignAction(rawAction, index, prefix, "default");
    case import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.form.runjs:
    case "runjs":
      return normalizeFieldRunJsAction(rawAction, index, prefix);
    default:
      (0, import_errors.throwBadRequest)(`Unsupported field linkage action "${String((rawAction == null ? void 0 : rawAction.name) ?? (rawAction == null ? void 0 : rawAction.type) ?? "")}".`);
  }
}
function compileBlockAction(action, index, prefix) {
  if (action.type === "setBlockState") {
    return {
      key: normalizeKey(action.key, prefix, index),
      name: import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.block.setBlockState,
      params: {
        value: action.state
      }
    };
  }
  return {
    key: normalizeKey(action.key, prefix, index),
    name: import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.block.runjs,
    params: {
      value: {
        script: action.code,
        ...action.version ? { version: action.version } : {}
      }
    }
  };
}
function compileActionAction(action, index, prefix) {
  if (action.type === "setActionState") {
    return {
      key: normalizeKey(action.key, prefix, index),
      name: import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.action.setActionState,
      params: {
        value: action.state
      }
    };
  }
  return {
    key: normalizeKey(action.key, prefix, index),
    name: import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES.action.runjs,
    params: {
      value: {
        script: action.code,
        ...action.version ? { version: action.version } : {}
      }
    }
  };
}
function compileFieldAssignItems(items, fallbackMode) {
  return items.map((item, itemIndex) => ({
    key: normalizeKey(item.key, `${fallbackMode}-item`, itemIndex),
    enable: normalizeBoolean(item.enabled, true),
    targetPath: normalizeFieldPath(item.targetPath, `${fallbackMode}.targetPath`),
    mode: fallbackMode,
    condition: compileReactionFilter(normalizeReactionFilter(item.when)),
    value: compileValueExpr(item.value)
  }));
}
function compileFieldAction(action, index, prefix, options) {
  const actionNames = import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES[options.scene];
  if (action.type === "setFieldState") {
    const actionName = actionNames.setFieldState;
    return {
      key: normalizeKey(action.key, prefix, index),
      name: actionName,
      params: {
        value: {
          fields: import_lodash.default.uniq(
            action.fieldPaths.map(
              (fieldPath) => {
                var _a;
                return ((_a = options.resolveFieldUid) == null ? void 0 : _a.call(options, fieldPath)) || normalizeFieldPath(fieldPath, "fieldPath");
              }
            )
          ),
          state: action.state
        }
      }
    };
  }
  if (action.type === "assignField") {
    if (!("assignField" in actionNames)) {
      (0, import_errors.throwBadRequest)(
        `Field linkage action "${action.type}" is not supported in scene "${options.scene}".`,
        import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_ACTION_FOR_SCENE
      );
    }
    return {
      key: normalizeKey(action.key, prefix, index),
      name: actionNames.assignField,
      params: {
        value: compileFieldAssignItems(action.items, "assign")
      }
    };
  }
  if (action.type === "setFieldDefaultValue") {
    if (!("setFieldDefaultValue" in actionNames)) {
      (0, import_errors.throwBadRequest)(
        `Field linkage action "${action.type}" is not supported in scene "${options.scene}".`,
        import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_ACTION_FOR_SCENE
      );
    }
    return {
      key: normalizeKey(action.key, prefix, index),
      name: actionNames.setFieldDefaultValue,
      params: {
        value: compileFieldAssignItems(action.items, "default")
      }
    };
  }
  return {
    key: normalizeKey(action.key, prefix, index),
    name: import_registry.FLOW_SURFACE_LINKAGE_CANONICAL_ACTION_NAMES[options.scene].runjs,
    params: {
      value: {
        script: action.code,
        ...action.version ? { version: action.version } : {}
      }
    }
  };
}
function assertScene(kind, scene) {
  const expectedScene = kind === "blockLinkage" ? "block" : "action";
  if (scene !== expectedScene) {
    (0, import_errors.throwBadRequest)(
      `${kind} only supports scene "${expectedScene}". Received "${scene}".`,
      import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_TARGET_KIND
    );
  }
}
function buildAllowedContextPathSet(operatorsByPath) {
  return new Set(Object.keys(operatorsByPath || {}).filter(Boolean));
}
function resolveAllowedContextPath(path, operatorsByPath) {
  if (operatorsByPath[path]) {
    return path;
  }
  const wildcardPath = Object.keys(operatorsByPath || {}).filter((candidate) => candidate.endsWith(".*")).sort((a, b) => b.length - a.length).find((candidate) => {
    const prefix = candidate.slice(0, -2);
    return path.startsWith(`${prefix}.`) && path.length > prefix.length + 1;
  });
  return wildcardPath || null;
}
function formatAllowedValues(values) {
  return values.length ? values.join(", ") : "(none)";
}
function validateContextBoundValuePath(rawPath, capabilityOrAllowedPaths, fieldName, code = import_errors2.FLOW_SURFACE_REACTION_INVALID_VALUE_PATH) {
  var _a;
  const path = extractBareContextPath(rawPath, `${fieldName}.path`);
  const operatorsByPath = capabilityOrAllowedPaths instanceof Set ? Object.fromEntries([...capabilityOrAllowedPaths].map((allowedPath) => [allowedPath, []])) : ((_a = capabilityOrAllowedPaths.conditionMeta) == null ? void 0 : _a.operatorsByPath) || {};
  if (!resolveAllowedContextPath(path, operatorsByPath)) {
    (0, import_errors.throwBadRequest)(`${fieldName}.path "${path}" is not available in the current reaction context.`, code);
  }
}
function validateContextBoundValue(value, capabilityOrAllowedPaths, fieldName) {
  if (import_lodash.default.isPlainObject(value) && value.source === "path") {
    validateContextBoundValuePath(value.path, capabilityOrAllowedPaths, fieldName);
    return;
  }
  if (Array.isArray(value)) {
    value.forEach((item, index) => validateContextBoundValue(item, capabilityOrAllowedPaths, `${fieldName}[${index}]`));
    return;
  }
  if (import_lodash.default.isPlainObject(value)) {
    for (const [key, item] of Object.entries(value)) {
      validateContextBoundValue(item, capabilityOrAllowedPaths, `${fieldName}.${key}`);
    }
  }
}
function validateReactionFilterAgainstCapability(filter, capability, prefix) {
  var _a;
  const operatorsByPath = ((_a = capability.conditionMeta) == null ? void 0 : _a.operatorsByPath) || {};
  const visit = (node, currentPrefix) => {
    var _a2, _b;
    if (!import_lodash.default.isPlainObject(node)) {
      return;
    }
    if (Array.isArray(node.items)) {
      node.items.forEach((item, index) => visit(item, `${currentPrefix}.items[${index}]`));
      return;
    }
    const hasOperator = "operator" in node;
    const hasValue = "value" in node;
    const hasPath = "path" in node;
    if (!hasOperator && !hasValue && !hasPath) {
      return;
    }
    if (!hasPath) {
      (0, import_errors.throwBadRequest)(
        `${currentPrefix}.path must be a non-empty string.`,
        import_errors2.FLOW_SURFACE_REACTION_INVALID_CONDITION_PATH
      );
    }
    const path = extractBareContextPath(node.path, `${currentPrefix}.path`);
    const operatorPath = resolveAllowedContextPath(path, operatorsByPath);
    if (!operatorPath) {
      (0, import_errors.throwBadRequest)(
        `${currentPrefix}.path "${path}" is not available in the current reaction context.`,
        import_errors2.FLOW_SURFACE_REACTION_INVALID_CONDITION_PATH
      );
    }
    const operator = typeof node.operator === "string" ? node.operator.trim() : "";
    const allowedOperators = operatorsByPath[operatorPath] || [];
    if (!operator) {
      (0, import_errors.throwBadRequest)(
        `${currentPrefix}.operator is required for path "${path}".`,
        import_errors2.FLOW_SURFACE_REACTION_INVALID_CONDITION_OPERATOR
      );
    }
    if (!allowedOperators.includes(operator)) {
      (0, import_errors.throwBadRequest)(
        `${currentPrefix}.operator "${operator}" is not supported for path "${path}". Supported operators: ${formatAllowedValues(
          allowedOperators
        )}.`,
        import_errors2.FLOW_SURFACE_REACTION_INVALID_CONDITION_OPERATOR
      );
    }
    if (hasValue) {
      const fieldMeta = (_b = (_a2 = capability.conditionMeta) == null ? void 0 : _a2.fieldMetaByPath) == null ? void 0 : _b[operatorPath];
      if (import_filter_group.FLOW_SURFACE_DATE_FILTER_OPERATORS.has(operator) || (0, import_filter_group.isFlowSurfaceDateLikeFieldMeta)(fieldMeta)) {
        (0, import_filter_group.normalizeFlowSurfaceDateConditionValue)(operator, node.value, `${currentPrefix}.value`, {
          fieldPath: path,
          fieldType: fieldMeta == null ? void 0 : fieldMeta.type,
          fieldInterface: fieldMeta == null ? void 0 : fieldMeta.interface,
          allowContextPathValue: true
        });
      }
      validateContextBoundValue(node.value, capability, `${currentPrefix}.value`);
    }
  };
  visit(filter, prefix);
}
function validateFieldAssignItemValue(item, capability, prefix) {
  var _a;
  const supportedSources = ((_a = capability.valueExprMeta) == null ? void 0 : _a.supportedSources) || [];
  if (!supportedSources.includes(item.value.source)) {
    (0, import_errors.throwBadRequest)(
      `${prefix}.value.source "${item.value.source}" is not supported. Supported sources: ${formatAllowedValues(
        supportedSources
      )}.`,
      import_errors2.FLOW_SURFACE_REACTION_INVALID_VALUE_SOURCE
    );
  }
  if (item.value.source === "path") {
    validateContextBoundValuePath(
      item.value.path,
      buildAllowedContextPathSet(capability.conditionMeta.operatorsByPath),
      `${prefix}.value`
    );
  }
}
function validateFieldAssignItemTarget(item, capability, prefix, mode) {
  const field = capability.targetFields.find((targetField) => targetField.path === item.targetPath);
  if (!field) {
    (0, import_errors.throwBadRequest)(
      `${prefix}.targetPath "${item.targetPath}" is not available in the current target fields.`,
      import_errors2.FLOW_SURFACE_REACTION_INVALID_TARGET_FIELD
    );
  }
  const supported = mode === "assign" ? field.supportsAssign : field.supportsDefault;
  if (!supported) {
    (0, import_errors.throwBadRequest)(
      `${prefix}.targetPath "${item.targetPath}" does not support ${mode === "assign" ? "assignment" : "default values"} in the current scene.`,
      import_errors2.FLOW_SURFACE_REACTION_INVALID_TARGET_FIELD
    );
  }
}
function buildReactionFingerprint(value) {
  return (0, import_node_crypto.createHash)("sha1").update(buildStableFingerprintString(value)).digest("hex");
}
function normalizeBlockLinkageRules(rawRules) {
  assertRuleArray(rawRules, "Block linkage rules");
  return rawRules.map((rawRule, index) => {
    const common = normalizeRuleCommon(rawRule, index, "block-linkage-rule");
    const rawActions = Array.isArray(rawRule == null ? void 0 : rawRule.then) ? rawRule.then : Array.isArray(rawRule == null ? void 0 : rawRule.actions) ? rawRule.actions : [];
    return {
      key: common.key,
      title: common.title,
      enabled: common.enabled,
      when: common.when,
      then: rawActions.map(
        (rawAction, actionIndex) => normalizeBlockAction(rawAction, actionIndex, `${common.key}-action`)
      )
    };
  });
}
function normalizeActionLinkageRules(rawRules) {
  assertRuleArray(rawRules, "Action linkage rules");
  return rawRules.map((rawRule, index) => {
    const common = normalizeRuleCommon(rawRule, index, "action-linkage-rule");
    const rawActions = Array.isArray(rawRule == null ? void 0 : rawRule.then) ? rawRule.then : Array.isArray(rawRule == null ? void 0 : rawRule.actions) ? rawRule.actions : [];
    return {
      key: common.key,
      title: common.title,
      enabled: common.enabled,
      when: common.when,
      then: rawActions.map(
        (rawAction, actionIndex) => normalizeActionAction(rawAction, actionIndex, `${common.key}-action`)
      )
    };
  });
}
function normalizeFieldLinkageRules(rawRules, options) {
  assertRuleArray(rawRules, "Field linkage rules");
  const normalized = rawRules.map((rawRule, index) => {
    const common = normalizeRuleCommon(rawRule, index, "field-linkage-rule");
    const rawActions = Array.isArray(rawRule == null ? void 0 : rawRule.then) ? rawRule.then : Array.isArray(rawRule == null ? void 0 : rawRule.actions) ? rawRule.actions : [];
    return {
      key: common.key,
      title: common.title,
      enabled: common.enabled,
      when: common.when,
      then: rawActions.map(
        (rawAction, actionIndex) => normalizeFieldAction(rawAction, actionIndex, `${common.key}-action`, options)
      )
    };
  });
  validateFieldLinkageSceneSupport(options.scene, normalized);
  return normalized;
}
function validateBlockLinkageSceneSupport(scene, rules) {
  assertScene("blockLinkage", scene);
  for (const rule of rules || []) {
    for (const action of rule.then || []) {
      if (action.type === "setBlockState" && !import_registry.FLOW_SURFACE_BLOCK_LINKAGE_STATES.includes(action.state)) {
        (0, import_errors.throwBadRequest)(
          `Block linkage state "${String(action.state)}" is not supported in scene "${scene}".`,
          import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_ACTION_FOR_SCENE
        );
      }
    }
  }
}
function validateBlockLinkageRulesAgainstCapability(rules, capability) {
  for (const [ruleIndex, rule] of (rules || []).entries()) {
    validateReactionFilterAgainstCapability(rule.when, capability, `rules[${ruleIndex}].when`);
  }
}
function validateActionLinkageSceneSupport(scene, rules) {
  assertScene("actionLinkage", scene);
  for (const rule of rules || []) {
    for (const action of rule.then || []) {
      if (action.type === "setActionState" && !import_registry.FLOW_SURFACE_ACTION_LINKAGE_STATES.includes(action.state)) {
        (0, import_errors.throwBadRequest)(
          `Action linkage state "${String(action.state)}" is not supported in scene "${scene}".`,
          import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_ACTION_FOR_SCENE
        );
      }
    }
  }
}
function validateActionLinkageRulesAgainstCapability(rules, capability) {
  for (const [ruleIndex, rule] of (rules || []).entries()) {
    validateReactionFilterAgainstCapability(rule.when, capability, `rules[${ruleIndex}].when`);
  }
}
function validateFieldLinkageSceneSupport(scene, rules) {
  const supportedActionTypes = import_registry.FLOW_SURFACE_FIELD_LINKAGE_ACTION_TYPES_BY_SCENE[scene];
  const supportedStates = import_registry.FLOW_SURFACE_FIELD_LINKAGE_STATES_BY_SCENE[scene];
  for (const rule of rules || []) {
    for (const action of rule.then || []) {
      if (!supportedActionTypes.includes(action.type)) {
        (0, import_errors.throwBadRequest)(
          `Field linkage action "${action.type}" is not supported in scene "${scene}".`,
          import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_ACTION_FOR_SCENE
        );
      }
      if (action.type === "setFieldState" && !supportedStates.includes(action.state)) {
        (0, import_errors.throwBadRequest)(
          `Field linkage state "${String(action.state)}" is not supported in scene "${scene}".`,
          import_errors2.FLOW_SURFACE_REACTION_UNSUPPORTED_ACTION_FOR_SCENE
        );
      }
    }
  }
}
function validateFieldLinkageRulesAgainstCapability(rules, capability) {
  for (const [ruleIndex, rule] of (rules || []).entries()) {
    validateReactionFilterAgainstCapability(rule.when, capability, `rules[${ruleIndex}].when`);
    for (const [actionIndex, action] of (rule.then || []).entries()) {
      if (action.type !== "assignField" && action.type !== "setFieldDefaultValue") {
        continue;
      }
      const mode = action.type === "assignField" ? "assign" : "default";
      for (const [itemIndex, item] of (action.items || []).entries()) {
        const itemPrefix = `rules[${ruleIndex}].then[${actionIndex}].items[${itemIndex}]`;
        validateFieldAssignItemTarget(item, capability, itemPrefix, mode);
        validateFieldAssignItemValue(item, capability, itemPrefix);
        validateReactionFilterAgainstCapability(item.when, capability, `${itemPrefix}.when`);
      }
    }
  }
}
function compileBlockLinkageCanonicalRules(rules) {
  validateBlockLinkageSceneSupport("block", rules);
  return normalizeBlockLinkageRules(rules).map((rule, index) => ({
    key: normalizeKey(rule.key, "block-linkage-rule", index),
    title: normalizeTitle(rule.title, index),
    enable: normalizeBoolean(rule.enabled, true),
    condition: compileReactionFilter(normalizeReactionFilter(rule.when)),
    actions: rule.then.map((action, actionIndex) => compileBlockAction(action, actionIndex, `${rule.key}-action`))
  }));
}
function compileActionLinkageCanonicalRules(rules) {
  validateActionLinkageSceneSupport("action", rules);
  return normalizeActionLinkageRules(rules).map((rule, index) => ({
    key: normalizeKey(rule.key, "action-linkage-rule", index),
    title: normalizeTitle(rule.title, index),
    enable: normalizeBoolean(rule.enabled, true),
    condition: compileReactionFilter(normalizeReactionFilter(rule.when)),
    actions: rule.then.map((action, actionIndex) => compileActionAction(action, actionIndex, `${rule.key}-action`))
  }));
}
function compileFieldLinkageCanonicalRules(rules, options) {
  validateFieldLinkageSceneSupport(options.scene, rules);
  return normalizeFieldLinkageRules(rules, { scene: options.scene }).map((rule, index) => ({
    key: normalizeKey(rule.key, "field-linkage-rule", index),
    title: normalizeTitle(rule.title, index),
    enable: normalizeBoolean(rule.enabled, true),
    condition: compileReactionFilter(normalizeReactionFilter(rule.when)),
    actions: rule.then.map(
      (action, actionIndex) => compileFieldAction(action, actionIndex, `${rule.key}-action`, options)
    )
  }));
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  buildReactionFingerprint,
  compileActionLinkageCanonicalRules,
  compileBlockLinkageCanonicalRules,
  compileFieldLinkageCanonicalRules,
  normalizeActionLinkageRules,
  normalizeBlockLinkageRules,
  normalizeFieldLinkageRules,
  validateActionLinkageRulesAgainstCapability,
  validateActionLinkageSceneSupport,
  validateBlockLinkageRulesAgainstCapability,
  validateBlockLinkageSceneSupport,
  validateFieldLinkageRulesAgainstCapability,
  validateFieldLinkageSceneSupport,
  validateReactionFilterAgainstCapability
});
