function normalizeDefinitionKey(key) {
  if (typeof key !== "string") return "";
  const trimmed = key.trim();
  return trimmed.length ? trimmed.toLowerCase() : "";
}
function normalizeDefinitionConfig(raw) {
  if (!raw) return {};
  if (typeof raw === "string") {
    try {
      const parsed = JSON.parse(raw);
      if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
        return { ...parsed };
      }
      return {};
    } catch {
      return {};
    }
  }
  if (typeof raw === "object" && !Array.isArray(raw)) {
    return { ...raw };
  }
  return {};
}
function normalizeFieldsetFilter(input) {
  if (input == null) return null;
  const values = Array.isArray(input) ? input : [input];
  const normalized = /* @__PURE__ */ new Set();
  for (const raw of values) {
    if (raw == null) continue;
    const trimmed = String(raw).trim();
    if (!trimmed) {
      normalized.add(null);
    } else {
      normalized.add(trimmed);
    }
  }
  return normalized.size ? normalized : null;
}
function toTimeMs(value) {
  if (value == null) return 0;
  if (value instanceof Date) return value.getTime();
  const parsed = new Date(value).getTime();
  return Number.isNaN(parsed) ? 0 : parsed;
}
function summarizeDefinitionRow(row) {
  const normalizedKey = normalizeDefinitionKey(row.key);
  if (!normalizedKey) return null;
  const cfg = normalizeDefinitionConfig(row.configJson);
  const label = typeof cfg.label === "string" && cfg.label.trim().length ? cfg.label.trim() : row.key;
  const dictionaryId = typeof cfg.dictionaryId === "string" && cfg.dictionaryId.trim().length ? cfg.dictionaryId.trim() : null;
  const multi = cfg.multi !== void 0 ? Boolean(cfg.multi) : false;
  const priority = typeof cfg.priority === "number" ? cfg.priority : 0;
  return {
    key: row.key,
    label,
    kind: typeof row.kind === "string" ? row.kind : null,
    multi,
    dictionaryId,
    organizationId: row.organizationId ?? null,
    tenantId: row.tenantId ?? null,
    priority,
    updatedAt: toTimeMs(row.updatedAt)
  };
}
function sortDefinitionSummaries(defs) {
  return [...defs].sort((a, b) => {
    const priorityDiff = (a.priority ?? 0) - (b.priority ?? 0);
    if (priorityDiff !== 0) return priorityDiff;
    const updatedDiff = (b.updatedAt ?? 0) - (a.updatedAt ?? 0);
    if (updatedDiff !== 0) return updatedDiff;
    return a.key.localeCompare(b.key);
  });
}
function selectDefinitionForRecord(defs, organizationId, tenantId) {
  if (!defs.length) return null;
  const prioritizedForOrg = defs.filter(
    (def) => def.organizationId && organizationId && def.organizationId === organizationId
  );
  if (prioritizedForOrg.length) return sortDefinitionSummaries(prioritizedForOrg)[0];
  const prioritizedForTenant = defs.filter(
    (def) => def.tenantId && tenantId && def.tenantId === tenantId && !def.organizationId
  );
  if (prioritizedForTenant.length) return sortDefinitionSummaries(prioritizedForTenant)[0];
  const global = defs.filter((def) => !def.organizationId);
  if (global.length) return sortDefinitionSummaries(global)[0];
  return sortDefinitionSummaries(defs)[0] ?? null;
}
function resolveCfDefIndexOrgCandidates(organizationIds, fallbackOrganizationId) {
  const source = Array.isArray(organizationIds) && organizationIds.length ? organizationIds : [fallbackOrganizationId ?? null];
  return source.map((id) => typeof id === "string" ? id.trim() : id).filter((id) => typeof id === "string" && id.length > 0);
}
function matchesFieldset(configJson, fieldsetFilter) {
  const config = normalizeDefinitionConfig(configJson);
  const fieldsets = Array.isArray(config.fieldsets) ? config.fieldsets.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0) : [];
  const fieldset = typeof config.fieldset === "string" && config.fieldset.trim().length > 0 ? config.fieldset.trim() : null;
  return fieldsets.length > 0 ? fieldsets.some((entry) => fieldsetFilter.has(entry)) : fieldsetFilter.has(fieldset);
}
function buildCustomFieldDefinitionIndexFromRows(rows, opts = {}) {
  const orgCandidates = opts.organizationIds ?? [];
  const fieldsetFilter = normalizeFieldsetFilter(opts.fieldset);
  const index = /* @__PURE__ */ new Map();
  for (const row of rows) {
    if (row.deletedAt != null) continue;
    const org = row.organizationId ?? null;
    if (org !== null && !(orgCandidates.length > 0 && orgCandidates.includes(org))) continue;
    if (fieldsetFilter && !matchesFieldset(row.configJson, fieldsetFilter)) continue;
    const summary = summarizeDefinitionRow(row);
    if (!summary) continue;
    const normalizedKey = normalizeDefinitionKey(summary.key);
    if (!normalizedKey) continue;
    if (!index.has(normalizedKey)) index.set(normalizedKey, []);
    index.get(normalizedKey).push(summary);
  }
  index.forEach((entries, key) => {
    index.set(key, sortDefinitionSummaries(entries));
  });
  return index;
}
function sameStringSet(a, b) {
  const left = new Set(a);
  const right = new Set(b);
  if (left.size !== right.size) return false;
  for (const value of left) {
    if (!right.has(value)) return false;
  }
  return true;
}
function canReuseCustomFieldDefinitions(resolved, request) {
  if (!resolved) return false;
  if ((resolved.tenantId ?? null) !== (request.tenantId ?? null)) return false;
  if (!sameStringSet(resolved.entityIds.map(String), request.entityIds.map(String))) return false;
  if (!sameStringSet(resolved.organizationIds, request.organizationIds)) return false;
  return true;
}
export {
  buildCustomFieldDefinitionIndexFromRows,
  canReuseCustomFieldDefinitions,
  normalizeDefinitionConfig,
  normalizeDefinitionKey,
  normalizeFieldsetFilter,
  resolveCfDefIndexOrgCandidates,
  selectDefinitionForRecord,
  sortDefinitionSummaries,
  summarizeDefinitionRow
};
//# sourceMappingURL=custom-field-definition-index.js.map
