/**
 * 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 field_value_exports = {};
__export(field_value_exports, {
  assertFieldValueTargetSupported: () => assertFieldValueTargetSupported,
  buildFieldValueWriteResult: () => buildFieldValueWriteResult,
  collectUpdateAssociationValuesFromFieldValueRules: () => collectUpdateAssociationValuesFromFieldValueRules,
  compileFieldValueRulesToCanonical: () => compileFieldValueRulesToCanonical,
  isFieldValueTargetUseSupported: () => isFieldValueTargetUseSupported,
  normalizeFieldValueRules: () => normalizeFieldValueRules,
  validateFieldValueRulesAgainstCapability: () => validateFieldValueRulesAgainstCapability
});
module.exports = __toCommonJS(field_value_exports);
var import_lodash = __toESM(require("lodash"));
var import_errors = require("../errors");
var import_filter_group = require("../filter-group");
var import_errors2 = require("./errors");
var import_fingerprint = require("./fingerprint");
var import_registry = require("./registry");
var import_value_expr = require("./value-expr");
const FLOW_SURFACE_FIELD_VALUE_SUPPORTED_USES = /* @__PURE__ */ new Set(["CreateFormModel", "EditFormModel"]);
const FLOW_SURFACE_FIELD_VALUE_SCENE = "form";
const FLOW_SURFACE_FIELD_VALUE_SLOT = (0, import_registry.getReactionSlot)(
  "fieldValue",
  FLOW_SURFACE_FIELD_VALUE_SCENE
);
function isFieldValueTargetUseSupported(use) {
  return FLOW_SURFACE_FIELD_VALUE_SUPPORTED_USES.has(String(use || "").trim());
}
function assertFieldValueTargetSupported(target) {
  if (isFieldValueTargetUseSupported(target == null ? void 0 : target.use)) {
    return;
  }
  const label = (target == null ? void 0 : target.publicPath) || (target == null ? void 0 : target.uid) || "target";
  (0, import_errors.throwBadRequest)(
    `flowSurfaces field value rules only support createForm/editForm targets; got '${label}' (${(target == null ? void 0 : target.use) || "unknown"})`,
    import_errors2.FLOW_SURFACE_REACTION_FORM_ONLY
  );
}
function normalizeFieldValueRule(rule, index) {
  const current = import_lodash.default.isPlainObject(rule) ? rule : {};
  const key = String(current.key || `idx:${index}`).trim();
  return {
    ...key ? { key } : {},
    enabled: current.enabled !== false,
    targetPath: (0, import_value_expr.normalizeReactionPath)(current.targetPath, `rules[${index}].targetPath`),
    mode: current.mode === "default" ? "default" : "assign",
    when: (0, import_value_expr.normalizeReactionFilter)(current.when),
    value: (0, import_value_expr.normalizeReactionValueExpr)(current.value)
  };
}
function normalizeFieldValueRules(rules) {
  const list = Array.isArray(rules) ? rules : [];
  return list.map((rule, index) => normalizeFieldValueRule(rule, index));
}
function validateFieldValueRulesAgainstCapability(rules, capability) {
  for (const [ruleIndex, rule] of (rules || []).entries()) {
    validateFieldValueDateConditionFilter(rule.when, capability, `rules[${ruleIndex}].when`);
  }
}
function validateFieldValueDateConditionFilter(filter, capability, prefix) {
  const visit = (node, currentPrefix) => {
    var _a;
    if (!import_lodash.default.isPlainObject(node)) {
      return;
    }
    if (Array.isArray(node.items)) {
      node.items.forEach((item, index) => visit(item, `${currentPrefix}.items[${index}]`));
      return;
    }
    const operator = typeof node.operator === "string" ? node.operator.trim() : "";
    const path = typeof node.path === "string" ? node.path.trim() : "";
    if (!operator || !path || !Object.prototype.hasOwnProperty.call(node, "value")) {
      return;
    }
    const fieldMeta = resolveFieldValueConditionFieldMeta(path, (_a = capability.conditionMeta) == null ? void 0 : _a.fieldMetaByPath);
    if (!import_filter_group.FLOW_SURFACE_DATE_FILTER_OPERATORS.has(operator) && !(0, import_filter_group.isFlowSurfaceDateLikeFieldMeta)(fieldMeta)) {
      return;
    }
    (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
    });
  };
  visit(filter, prefix);
}
function resolveFieldValueConditionFieldMeta(path, fieldMetaByPath) {
  if (!fieldMetaByPath) {
    return void 0;
  }
  if (fieldMetaByPath[path]) {
    return fieldMetaByPath[path];
  }
  const wildcardPath = Object.keys(fieldMetaByPath).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 ? fieldMetaByPath[wildcardPath] : void 0;
}
function compileFieldValueRulesToCanonical(rules) {
  return normalizeFieldValueRules(rules).map((rule) => ({
    key: rule.key,
    enable: rule.enabled !== false,
    targetPath: rule.targetPath,
    mode: rule.mode === "default" ? "default" : "assign",
    condition: (0, import_value_expr.compileReactionFilter)(rule.when),
    value: (0, import_value_expr.compileReactionValueExpr)(rule.value)
  }));
}
function collectUpdateAssociationValuesFromFieldValueRules(items, rootCollection) {
  const list = Array.isArray(items) ? items : [];
  const output = /* @__PURE__ */ new Set();
  const getDeepestAssociationPath = (targetPath) => {
    var _a, _b, _c;
    if (!rootCollection || typeof rootCollection.getField !== "function") return null;
    if (typeof targetPath !== "string" || !targetPath.includes(".")) return null;
    const segments = targetPath.split(".").filter(Boolean);
    if (segments.length < 2) return null;
    let currentCollection = rootCollection;
    const associationSegments = [];
    let deepest = null;
    let deepestField = null;
    for (let index = 0; index < segments.length - 1; index += 1) {
      const segment = segments[index];
      const field = (_a = currentCollection == null ? void 0 : currentCollection.getField) == null ? void 0 : _a.call(currentCollection, segment);
      if (!((_b = field == null ? void 0 : field.isAssociationField) == null ? void 0 : _b.call(field)) || !(field == null ? void 0 : field.targetCollection)) break;
      associationSegments.push(segment);
      deepest = associationSegments.join(".");
      deepestField = field;
      currentCollection = field.targetCollection;
    }
    if (deepest && deepestField) {
      const leaf = segments[segments.length - 1];
      const rawKey = (deepestField == null ? void 0 : deepestField.targetKey) ?? ((_c = deepestField == null ? void 0 : deepestField.targetCollection) == null ? void 0 : _c.filterTargetKey) ?? "id";
      const keyFields = Array.isArray(rawKey) ? rawKey.filter((value) => typeof value === "string" && !!value) : typeof rawKey === "string" && rawKey ? [rawKey] : ["id"];
      if (typeof leaf === "string" && keyFields.includes(leaf)) {
        return null;
      }
    }
    return deepest;
  };
  for (const item of list) {
    const targetPath = typeof (item == null ? void 0 : item.targetPath) === "string" ? item.targetPath : "";
    if (!targetPath) continue;
    const associationPath = getDeepestAssociationPath(targetPath);
    if (associationPath) {
      output.add(associationPath);
    }
  }
  return Array.from(output);
}
function buildFieldValueWriteResult(params) {
  assertFieldValueTargetSupported(params.target);
  const normalizedRules = normalizeFieldValueRules(params.rules);
  const canonicalRules = normalizedRules.map((rule) => ({
    key: rule.key,
    enable: rule.enabled !== false,
    targetPath: rule.targetPath,
    mode: rule.mode,
    condition: (0, import_value_expr.compileReactionFilter)(rule.when),
    value: (0, import_value_expr.compileReactionValueExpr)(rule.value)
  }));
  const fingerprint = (0, import_fingerprint.buildReactionFingerprint)({
    kind: "fieldValue",
    scene: FLOW_SURFACE_FIELD_VALUE_SCENE,
    slot: FLOW_SURFACE_FIELD_VALUE_SLOT,
    canonicalRules
  });
  return {
    target: {
      uid: params.target.uid,
      ...params.target.publicPath ? { publicPath: params.target.publicPath } : {}
    },
    resolvedScene: FLOW_SURFACE_FIELD_VALUE_SCENE,
    resolvedSlot: FLOW_SURFACE_FIELD_VALUE_SLOT,
    fingerprint,
    normalizedRules,
    canonicalRules,
    updateAssociationValues: collectUpdateAssociationValuesFromFieldValueRules(
      canonicalRules,
      params.target.collection
    )
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  assertFieldValueTargetSupported,
  buildFieldValueWriteResult,
  collectUpdateAssociationValuesFromFieldValueRules,
  compileFieldValueRulesToCanonical,
  isFieldValueTargetUseSupported,
  normalizeFieldValueRules,
  validateFieldValueRulesAgainstCapability
});
