/**
 * 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 association_title_field_exports = {};
__export(association_title_field_exports, {
  assertCollectionTitleFieldExists: () => assertCollectionTitleFieldExists,
  assertFlowSurfaceTitleFieldIsNotId: () => assertFlowSurfaceTitleFieldIsNotId,
  buildFlowSurfaceTitleFieldErrorDetails: () => buildFlowSurfaceTitleFieldErrorDetails,
  getExplicitCollectionTitleFieldName: () => getExplicitCollectionTitleFieldName,
  getFlowSurfaceTitleFieldCandidateNames: () => getFlowSurfaceTitleFieldCandidateNames,
  isTitleableCollectionField: () => isTitleableCollectionField,
  normalizeFlowSurfaceTitleField: () => normalizeFlowSurfaceTitleField,
  resolveAssociationSafeTitleField: () => resolveAssociationSafeTitleField,
  resolveAssociationTitleFieldTargetCollection: () => resolveAssociationTitleFieldTargetCollection,
  resolveCollectionSafeTitleField: () => resolveCollectionSafeTitleField
});
module.exports = __toCommonJS(association_title_field_exports);
var import_errors = require("./errors");
var import_service_helpers = require("./service-helpers");
const FALLBACK_TITLE_USABLE_INTERFACES = /* @__PURE__ */ new Set([
  "attachmentURL",
  "date",
  "datetime",
  "datetimeNoTz",
  "email",
  "formula",
  "id",
  "input",
  "integer",
  "nanoid",
  "number",
  "percent",
  "phone",
  "radioGroup",
  "select",
  "sequence",
  "snowflakeId",
  "sort",
  "space",
  "textarea",
  "time",
  "unixTimestamp",
  "url",
  "uuid",
  "vditor"
]);
const LAST_RESORT_TITLE_FIELD_NAMES = /* @__PURE__ */ new Set(["createdAt", "updatedAt"]);
const LAST_RESORT_TITLE_FIELD_INTERFACES = /* @__PURE__ */ new Set(["createdAt", "updatedAt"]);
const TITLE_FIELD_CANDIDATE_LIMIT = 20;
function isTitleableCollectionField(field) {
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
  const configured = (field == null ? void 0 : field.titleable) ?? (field == null ? void 0 : field.titleUsable) ?? ((_a = field == null ? void 0 : field.options) == null ? void 0 : _a.titleable) ?? ((_b = field == null ? void 0 : field.options) == null ? void 0 : _b.titleUsable);
  if (typeof configured === "boolean") {
    return configured;
  }
  const interfaceOptions = typeof (field == null ? void 0 : field.getInterfaceOptions) === "function" ? field.getInterfaceOptions() : void 0;
  if (typeof (interfaceOptions == null ? void 0 : interfaceOptions.titleUsable) === "boolean") {
    return interfaceOptions.titleUsable;
  }
  const interfaceName = typeof (field == null ? void 0 : field.interface) === "string" ? field.interface : typeof ((_c = field == null ? void 0 : field.options) == null ? void 0 : _c.interface) === "string" ? field.options.interface : void 0;
  const interfaceCtor = ((_f = (_e = (_d = field == null ? void 0 : field.collection) == null ? void 0 : _d.collectionManager) == null ? void 0 : _e.getFieldInterface) == null ? void 0 : _f.call(_e, interfaceName)) || ((_j = (_i = (_h = (_g = field == null ? void 0 : field.collection) == null ? void 0 : _g.db) == null ? void 0 : _h.interfaceManager) == null ? void 0 : _i.getInterfaceType) == null ? void 0 : _j.call(_i, interfaceName));
  if (interfaceCtor) {
    const interfaceInstance = typeof interfaceCtor === "function" ? new interfaceCtor(void 0) : interfaceCtor;
    if (typeof (interfaceInstance == null ? void 0 : interfaceInstance.titleUsable) === "boolean") {
      return interfaceInstance.titleUsable;
    }
  }
  return !!(interfaceName && FALLBACK_TITLE_USABLE_INTERFACES.has(interfaceName));
}
function getExplicitCollectionTitleFieldName(collection) {
  var _a;
  const explicit = (_a = collection == null ? void 0 : collection.options) == null ? void 0 : _a.titleField;
  return typeof explicit === "string" ? explicit.trim() || void 0 : void 0;
}
function normalizeFlowSurfaceTitleField(value) {
  if (typeof value !== "string") {
    return void 0;
  }
  const normalized = value.trim();
  return normalized || void 0;
}
function getFlowSurfaceTitleFieldCandidateNames(collection, limit = TITLE_FIELD_CANDIDATE_LIMIT) {
  const candidates = (0, import_service_helpers.getCollectionFields)(collection).filter((field) => {
    const fieldName = (0, import_service_helpers.getFieldName)(field);
    return !!fieldName && !isIdTitleFieldName(fieldName) && !(0, import_service_helpers.isAssociationField)(field);
  }).map(import_service_helpers.getFieldName).filter(Boolean);
  return {
    availableFields: candidates.slice(0, limit),
    availableFieldsTruncated: candidates.length > limit
  };
}
function buildDefinedTitleFieldDetails(details) {
  return Object.fromEntries(Object.entries(details).filter(([, value]) => typeof value !== "undefined"));
}
function buildFlowSurfaceTitleFieldErrorDetails(options = {}, candidates = getFlowSurfaceTitleFieldCandidateNames(options.targetCollection)) {
  const { availableFields, availableFieldsTruncated } = candidates;
  return buildDefinedTitleFieldDetails({
    action: options.action,
    fieldPath: options.fieldPath,
    titleField: options.titleField,
    targetCollection: getTitleFieldTargetCollectionName(options),
    invalidReason: options.invalidReason,
    availableFields: availableFields.length ? availableFields : void 0,
    availableFieldsTruncated: availableFieldsTruncated || void 0,
    suggestion: buildTitleFieldSuggestion(options, availableFields),
    ...options.details
  });
}
function getTitleFieldTargetCollectionName(options) {
  return String(options.targetCollectionName || "").trim() || (0, import_service_helpers.getCollectionName)(options.targetCollection) || void 0;
}
function buildTitleFieldSuggestion(options, availableFields) {
  const targetCollectionName = getTitleFieldTargetCollectionName(options);
  const target = targetCollectionName ? ` on target collection '${targetCollectionName}'` : "";
  if (availableFields.length) {
    return `Use one of: ${availableFields.join(", ")}.`;
  }
  return `Set titleField to a readable non-association field${target}.`;
}
function buildTitleFieldGuidance(options, availableFields) {
  const targetCollectionName = getTitleFieldTargetCollectionName(options);
  const target = targetCollectionName ? ` on target collection '${targetCollectionName}'` : "";
  const suggestion = availableFields.length ? ` Use one of: ${availableFields.join(", ")}.` : "";
  return `; relation titleField must be a readable non-association field${target}.${suggestion}`;
}
function throwTitleFieldBadRequest(baseMessage, ruleId, options = {}) {
  const candidates = getFlowSurfaceTitleFieldCandidateNames(options.targetCollection);
  const details = buildFlowSurfaceTitleFieldErrorDetails(options, candidates);
  const errorOptions = buildDefinedTitleFieldDetails({
    path: options.path,
    ruleId,
    details
  });
  (0, import_errors.throwBadRequest)(`${baseMessage}${buildTitleFieldGuidance(options, candidates.availableFields)}`, errorOptions);
}
function assertFlowSurfaceTitleFieldIsNotId(value, options = {}) {
  const normalizedTitleField = normalizeFlowSurfaceTitleField(value);
  if (normalizedTitleField === "id") {
    throwTitleFieldBadRequest("flowSurfaces titleField cannot use 'id'", "relation-titleField-unreadable", {
      ...options,
      titleField: normalizedTitleField,
      invalidReason: options.invalidReason || "id"
    });
  }
}
function getAssociationConfiguredLabelFieldName(field) {
  var _a, _b, _c, _d, _e, _f, _g;
  return normalizeFlowSurfaceTitleField((_c = (_b = (_a = field == null ? void 0 : field.uiSchema) == null ? void 0 : _a["x-component-props"]) == null ? void 0 : _b.fieldNames) == null ? void 0 : _c.label) || normalizeFlowSurfaceTitleField((_g = (_f = (_e = (_d = field == null ? void 0 : field.options) == null ? void 0 : _d.uiSchema) == null ? void 0 : _e["x-component-props"]) == null ? void 0 : _f.fieldNames) == null ? void 0 : _g.label);
}
function isLastResortTitleField(field) {
  const fieldName = (0, import_service_helpers.getFieldName)(field);
  if (fieldName && LAST_RESORT_TITLE_FIELD_NAMES.has(fieldName)) {
    return true;
  }
  const fieldInterface = (0, import_service_helpers.getFieldInterface)(field);
  return !!(fieldInterface && LAST_RESORT_TITLE_FIELD_INTERFACES.has(fieldInterface));
}
function isIdTitleFieldName(value) {
  return normalizeFlowSurfaceTitleField(value) === "id";
}
function assertCollectionTitleFieldExists(collection, fieldName, options = {}) {
  const normalizedFieldName = typeof fieldName === "string" ? fieldName.trim() : String(fieldName || "").trim();
  if (!normalizedFieldName) {
    throwTitleFieldBadRequest(
      "flowSurfaces association titleField must be a non-empty string",
      "relation-titleField-invalid-shape",
      {
        ...options,
        targetCollection: collection,
        invalidReason: "empty"
      }
    );
  }
  assertFlowSurfaceTitleFieldIsNotId(normalizedFieldName, {
    ...options,
    targetCollection: collection
  });
  const field = (0, import_service_helpers.resolveFieldFromCollection)(collection, normalizedFieldName);
  if (!field) {
    throwTitleFieldBadRequest(
      `flowSurfaces collection '${(0, import_service_helpers.getCollectionName)(collection) || "unknown"}' titleField '${normalizedFieldName}' not found`,
      "relation-titleField-unknown",
      {
        ...options,
        targetCollection: collection,
        titleField: normalizedFieldName,
        invalidReason: "missing"
      }
    );
  }
  if ((0, import_service_helpers.isAssociationField)(field)) {
    throwTitleFieldBadRequest(
      `flowSurfaces collection '${(0, import_service_helpers.getCollectionName)(collection) || "unknown"}' titleField '${normalizedFieldName}' is not readable`,
      "relation-titleField-unreadable",
      {
        ...options,
        targetCollection: collection,
        titleField: normalizedFieldName,
        invalidReason: "association"
      }
    );
  }
  return field;
}
function resolveCollectionSafeTitleField(collection, options = {}) {
  if (!collection) {
    return null;
  }
  const explicitTitleField = getExplicitCollectionTitleFieldName(collection);
  if (explicitTitleField) {
    const field = assertCollectionTitleFieldExists(collection, explicitTitleField, options);
    return {
      field,
      fieldName: (0, import_service_helpers.getFieldName)(field) || explicitTitleField,
      source: "explicit",
      targetCollection: collection
    };
  }
  const isSafeTitleableField = (field) => !!(0, import_service_helpers.getFieldName)(field) && !isIdTitleFieldName((0, import_service_helpers.getFieldName)(field)) && !(0, import_service_helpers.isAssociationField)(field) && isTitleableCollectionField(field);
  const firstTitleableField = (0, import_service_helpers.getCollectionFields)(collection).find(isSafeTitleableField);
  if (!firstTitleableField) {
    return null;
  }
  const preferredTitleableField = (0, import_service_helpers.getCollectionFields)(collection).find((field) => isSafeTitleableField(field) && !isLastResortTitleField(field)) || firstTitleableField;
  return {
    field: preferredTitleableField,
    fieldName: (0, import_service_helpers.getFieldName)(preferredTitleableField),
    source: "firstTitleable",
    targetCollection: collection
  };
}
function resolveAssociationTitleFieldTargetCollection(field, dataSourceKey, getCollection) {
  return (0, import_service_helpers.resolveFieldTargetCollection)(field, dataSourceKey, getCollection) || null;
}
function resolveAssociationSafeTitleField(field, dataSourceKey, getCollection, options = {}) {
  const targetCollection = resolveAssociationTitleFieldTargetCollection(field, dataSourceKey, getCollection);
  if (!targetCollection) {
    return null;
  }
  const titleFieldErrorOptions = {
    ...options,
    targetCollection
  };
  const configuredLabelFieldName = getAssociationConfiguredLabelFieldName(field);
  if (configuredLabelFieldName) {
    assertFlowSurfaceTitleFieldIsNotId(configuredLabelFieldName, {
      ...titleFieldErrorOptions,
      titleField: configuredLabelFieldName
    });
    const configuredLabelField = (0, import_service_helpers.resolveFieldFromCollection)(targetCollection, configuredLabelFieldName);
    if (configuredLabelField) {
      assertCollectionTitleFieldExists(targetCollection, configuredLabelFieldName, {
        ...titleFieldErrorOptions,
        titleField: configuredLabelFieldName
      });
      return {
        field: configuredLabelField,
        fieldName: configuredLabelFieldName,
        source: "relationFieldLabel",
        targetCollection
      };
    }
  }
  const resolved = resolveCollectionSafeTitleField(targetCollection, titleFieldErrorOptions);
  if (!resolved) {
    return null;
  }
  return {
    ...resolved,
    targetCollection
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  assertCollectionTitleFieldExists,
  assertFlowSurfaceTitleFieldIsNotId,
  buildFlowSurfaceTitleFieldErrorDetails,
  getExplicitCollectionTitleFieldName,
  getFlowSurfaceTitleFieldCandidateNames,
  isTitleableCollectionField,
  normalizeFlowSurfaceTitleField,
  resolveAssociationSafeTitleField,
  resolveAssociationTitleFieldTargetCollection,
  resolveCollectionSafeTitleField
});
