import { createLogger } from "../logger/index.js";
const logger = createLogger("shared").child({ component: "query" });
const REASON_HINTS = {
  "search-disabled": "OM_SEARCH_ENABLED is off, so the filter runs as ILIKE against ciphertext and matches nothing.",
  "no-indexable-tokens": "The filter value produced no search tokens, so it runs as ILIKE against ciphertext and matches nothing. Use at least OM_SEARCH_MIN_LEN indexable characters, or filter on the deterministic hash column.",
  "no-search-tokens": "No search_tokens exist for this entity and scope, so the filter runs as ILIKE against ciphertext and matches nothing. Index the entity through query_index and reindex, or filter on the deterministic hash column.",
  "raw-orm-filter": "This filter bypasses the query engine, so it runs as ILIKE against ciphertext and matches nothing. Resolve ids through findEntityIdsBySearchTokens (@open-mercato/shared/lib/search/tokenLookup), filter on the deterministic hash column, or compare in memory after decryption."
};
const WARN_CACHE_CAP = 5e3;
const warned = /* @__PURE__ */ new Set();
const warnKey = (entity, tenantId, field) => `${entity}|${tenantId ?? "null"}|${field}`;
const normalizeColumnName = (value) => value.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
function resetCiphertextLikeWarnCache() {
  warned.clear();
}
async function warnOnCiphertextLikeFallback(params) {
  const { entity, tenantId, reason, service } = params;
  if (!service || service.isEnabled?.() === false) return;
  if (typeof service.getEncryptedFieldNames !== "function") return;
  const candidates = params.fields.filter((field) => typeof field === "string" && !field.startsWith("cf:")).map((field) => normalizeColumnName(field)).filter((field, index, all) => field.length > 0 && all.indexOf(field) === index).filter((field) => !warned.has(warnKey(entity, tenantId, field)));
  if (!candidates.length) return;
  try {
    const encrypted = new Set(
      (await service.getEncryptedFieldNames(entity, tenantId, null)).map(
        (field) => normalizeColumnName(String(field))
      )
    );
    for (const field of candidates) {
      if (!encrypted.has(field)) continue;
      if (warned.size >= WARN_CACHE_CAP) warned.clear();
      warned.add(warnKey(entity, tenantId, field));
      logger.warn("Text search filter cannot match an encrypted column", {
        entity,
        field,
        reason,
        hint: REASON_HINTS[reason]
      });
    }
  } catch (err) {
    logger.debug("Ciphertext search warning check failed", {
      entity,
      err: err instanceof Error ? err.message : String(err)
    });
  }
}
export {
  normalizeColumnName,
  resetCiphertextLikeWarnCache,
  warnOnCiphertextLikeFallback
};
//# sourceMappingURL=ciphertext-search-warning.js.map
