import { CUSTOMER_INTERACTION_TASK_SOURCE, EXAMPLE_TODO_SOURCE } from "./lib/interactionCompatibility.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
function assertTenantContext(ctx) {
  if (typeof ctx.tenantId !== "string" || ctx.tenantId.length === 0) {
    throw new Error("[search.customers] Missing tenantId in search build context");
  }
}
const entityIdCache = /* @__PURE__ */ new Map();
const profileEntityCache = /* @__PURE__ */ new WeakMap();
const todoCache = /* @__PURE__ */ new WeakMap();
const CUSTOMER_ENTITY_FIELDS = [
  "id",
  "kind",
  "display_name",
  "description",
  "primary_email",
  "primary_phone",
  "status",
  "lifecycle_stage",
  "owner_user_id",
  "source",
  "next_interaction_at",
  "next_interaction_name",
  "next_interaction_ref_id",
  "next_interaction_icon",
  "next_interaction_color",
  "organization_id",
  "tenant_id",
  "created_at",
  "updated_at",
  "deleted_at"
];
const CUSTOMER_CUSTOM_FIELD_SOURCES = [
  {
    entityId: "customers:customer_person_profile",
    table: "customer_people",
    alias: "person_profile",
    recordIdColumn: "id",
    join: { fromField: "id", toField: "entity_id" }
  },
  {
    entityId: "customers:customer_company_profile",
    table: "customer_companies",
    alias: "company_profile",
    recordIdColumn: "id",
    join: { fromField: "id", toField: "entity_id" }
  }
];
function extractCustomFieldMap(source) {
  if (!source) return {};
  const result = {};
  for (const [key, value] of Object.entries(source)) {
    if (value === void 0) continue;
    if (key.startsWith("cf:")) {
      result[key.slice(3)] = value;
    } else if (key.startsWith("cf_")) {
      result[key.slice(3)] = value;
    }
  }
  return result;
}
function normalizeCustomerEntity(row) {
  const normalized = {
    id: row.id ?? row.entity_id ?? row.entityId ?? null,
    kind: row.kind ?? null
  };
  const assign = (snake, camel) => {
    const value = row[snake] ?? (camel ? row[camel] : void 0);
    if (value !== void 0) {
      normalized[snake] = value;
      if (camel) normalized[camel] = value;
    }
  };
  assign("display_name", "displayName");
  assign("description");
  assign("primary_email", "primaryEmail");
  assign("primary_phone", "primaryPhone");
  assign("status");
  assign("lifecycle_stage", "lifecycleStage");
  assign("owner_user_id", "ownerUserId");
  assign("source");
  assign("next_interaction_at", "nextInteractionAt");
  assign("next_interaction_name", "nextInteractionName");
  assign("next_interaction_ref_id", "nextInteractionRefId");
  assign("next_interaction_icon", "nextInteractionIcon");
  assign("next_interaction_color", "nextInteractionColor");
  assign("organization_id", "organizationId");
  assign("tenant_id", "tenantId");
  assign("created_at", "createdAt");
  assign("updated_at", "updatedAt");
  assign("deleted_at", "deletedAt");
  return normalized;
}
function getProfileCache(record) {
  let cache = profileEntityCache.get(record);
  if (!cache) {
    cache = {};
    profileEntityCache.set(record, cache);
  }
  return cache;
}
function subtractCustomFields(primary, secondary) {
  if (!secondary || Object.keys(secondary).length === 0) return {};
  const primaryKeys = new Set(Object.keys(primary));
  const result = {};
  for (const [key, value] of Object.entries(secondary)) {
    if (!primaryKeys.has(key)) {
      result[key] = value;
    }
  }
  return result;
}
async function loadCustomerEntityBundle(ctx, opts) {
  if (!ctx.queryEngine) return null;
  const filters = {};
  const resolvedEntityId = typeof opts.entityId === "string" && opts.entityId.length ? opts.entityId : null;
  const resolvedProfileId = opts.profileId != null && String(opts.profileId).trim().length > 0 ? String(opts.profileId).trim() : null;
  const shouldJoinProfileSource = Boolean(opts.profileKind && resolvedProfileId && !resolvedEntityId);
  if (resolvedEntityId) {
    filters.id = { $eq: resolvedEntityId };
  }
  if (shouldJoinProfileSource) {
    const alias = opts.profileKind === "person" ? "person_profile" : "company_profile";
    filters[`${alias}.id`] = { $eq: resolvedProfileId };
  }
  if (!Object.keys(filters).length) return null;
  try {
    const result = await ctx.queryEngine.query("customers:customer_entity", {
      tenantId: ctx.tenantId,
      organizationId: ctx.organizationId ?? void 0,
      filters,
      includeCustomFields: true,
      ...shouldJoinProfileSource ? { customFieldSources: CUSTOMER_CUSTOM_FIELD_SOURCES } : {},
      fields: CUSTOMER_ENTITY_FIELDS,
      page: { page: 1, pageSize: 1 }
    });
    const row = result.items[0];
    if (!row) return null;
    const entity = normalizeCustomerEntity(row);
    const customFields = extractCustomFieldMap(row);
    return { entity, customFields };
  } catch (error) {
    logger.warn("Failed to load customer entity via QueryEngine", {
      component: "search",
      entityId: resolvedEntityId ?? null,
      profileKind: opts.profileKind ?? null,
      profileId: resolvedProfileId ?? null,
      err: error
    });
    return null;
  }
}
async function loadCustomerEntityForProfile(ctx, kind) {
  const cache = getProfileCache(ctx.record);
  if (cache[kind] !== void 0) return cache[kind] ?? null;
  const entityIdHint = resolveCustomerEntityId(ctx.record);
  const profileIdRaw = ctx.record.id ?? null;
  const profileId = profileIdRaw != null ? String(profileIdRaw) : null;
  if (!entityIdHint && !profileId) {
    cache[kind] = null;
    return null;
  }
  const loaded = await loadCustomerEntityBundle(ctx, {
    entityId: entityIdHint,
    profileKind: kind,
    profileId
  });
  cache[kind] = loaded ?? null;
  const resolvedId = loaded?.entity?.id ?? entityIdHint;
  if (resolvedId && typeof resolvedId === "string") {
    ctx.record.entity_id ??= resolvedId;
    ctx.record.entityId ??= resolvedId;
    entityIdCache.set(resolvedId, loaded ?? null);
  }
  if (loaded?.entity) {
    if (!ctx.record.entity) ctx.record.entity = loaded.entity;
    if (!ctx.record.customer_entity) ctx.record.customer_entity = loaded.entity;
  }
  return loaded ?? null;
}
async function loadCustomerEntityById(ctx, entityId) {
  const resolvedId = typeof entityId === "string" && entityId.length ? entityId : null;
  if (!resolvedId) return null;
  if (entityIdCache.has(resolvedId)) {
    return entityIdCache.get(resolvedId) ?? null;
  }
  const loaded = await loadCustomerEntityBundle(ctx, { entityId: resolvedId });
  entityIdCache.set(resolvedId, loaded ?? null);
  return loaded ?? null;
}
async function getCustomerEntity(ctx, entityId) {
  const profileCache = profileEntityCache.get(ctx.record);
  if (profileCache) {
    const cached = Object.values(profileCache).find((entry) => {
      if (!entry?.entity) return false;
      if (!entityId) return true;
      return entry.entity.id === entityId;
    });
    if (cached?.entity) return cached.entity;
  }
  const inline = getInlineCustomerEntity(ctx.record);
  if (inline && (!entityId || inline.id === entityId)) {
    if (inline.id && typeof inline.id === "string") {
      entityIdCache.set(inline.id, { entity: inline, customFields: {} });
    }
    return inline;
  }
  const resolvedId = entityId ?? resolveCustomerEntityId(ctx.record);
  const loaded = await loadCustomerEntityById(ctx, resolvedId);
  return loaded?.entity ?? null;
}
async function hydrateProfileContext(ctx, kind) {
  const profileCustomFields = ctx.customFields ?? {};
  const loaded = await loadCustomerEntityForProfile(ctx, kind);
  let entity = loaded?.entity ?? getInlineCustomerEntity(ctx.record);
  let entityCustomFields = loaded?.customFields ?? {};
  let entityId = entity?.id ?? resolveCustomerEntityId(ctx.record);
  if (!entity && entityId) {
    const fetched = await loadCustomerEntityById(ctx, entityId);
    entity = fetched?.entity ?? null;
    if (fetched?.customFields) {
      entityCustomFields = Object.keys(entityCustomFields).length ? entityCustomFields : fetched.customFields;
    }
  }
  if (!entity && !entityId) {
    entityId = resolveCustomerEntityId(ctx.record);
  }
  if (entity?.id && typeof entity.id === "string") {
    entityId = entity.id;
    ctx.record.entity_id ??= entity.id;
    ctx.record.entityId ??= entity.id;
    if (!ctx.record.entity) ctx.record.entity = entity;
    if (!ctx.record.customer_entity) ctx.record.customer_entity = entity;
  }
  const entityOnlyCustomFields = subtractCustomFields(profileCustomFields, entityCustomFields);
  return {
    entity: entity ?? null,
    entityId: entityId ?? null,
    profileCustomFields,
    entityCustomFields,
    entityOnlyCustomFields
  };
}
async function loadRecord(ctx, entityId, recordId) {
  if (!recordId || !ctx.queryEngine) return null;
  const res = await ctx.queryEngine.query(entityId, {
    tenantId: ctx.tenantId,
    organizationId: ctx.organizationId ?? void 0,
    filters: { id: recordId },
    includeCustomFields: true,
    page: { page: 1, pageSize: 1 }
  });
  return res.items[0];
}
function resolveCustomerEntityId(record) {
  const direct = record.customer_entity_id ?? record.entityId ?? record.entity_id ?? record.customerEntityId ?? record.customerEntityID ?? (typeof record.entity === "object" && record.entity ? record.entity.id : void 0) ?? (typeof record.customer_entity === "object" && record.customer_entity ? record.customer_entity.id : void 0);
  const value = typeof direct === "string" && direct.length ? direct : null;
  return value;
}
function getInlineCustomerEntity(record) {
  const inline = typeof record.entity === "object" && record.entity || typeof record.customer_entity === "object" && record.customer_entity || null;
  return inline;
}
async function getLinkedTodo(ctx) {
  if (todoCache.has(ctx.record)) {
    return todoCache.get(ctx.record);
  }
  const sourceRaw = typeof ctx.record.todo_source === "string" ? ctx.record.todo_source : EXAMPLE_TODO_SOURCE;
  const [moduleId, entityName] = sourceRaw.split(":");
  const entityId = moduleId && entityName ? `${moduleId}:${entityName}` : CUSTOMER_INTERACTION_TASK_SOURCE;
  const todo = await loadRecord(ctx, entityId, ctx.record.todo_id ?? ctx.record.todoId);
  todoCache.set(ctx.record, todo ?? null);
  return todo ?? null;
}
function buildCustomerUrl(kind, id) {
  if (!id) return null;
  const encoded = encodeURIComponent(id);
  if (kind === "person") return `/backend/customers/people-v2/${encoded}`;
  if (kind === "company") return `/backend/customers/companies-v2/${encoded}`;
  return `/backend/customers/companies-v2/${encoded}`;
}
function formatDealValue(record) {
  const amount = record.value_amount ?? record.valueAmount;
  if (!amount) return void 0;
  const currency = record.value_currency ?? record.valueCurrency ?? "";
  return currency ? `${amount} ${currency}` : String(amount);
}
function snippet(text, max = 140) {
  if (typeof text !== "string") return void 0;
  const trimmed = text.trim();
  if (!trimmed.length) return void 0;
  if (trimmed.length <= max) return trimmed;
  return `${trimmed.slice(0, max - 3)}...`;
}
function appendLine(lines, label, value) {
  if (value === null || value === void 0) return;
  const text = Array.isArray(value) ? value.map((item) => item === null || item === void 0 ? "" : String(item)).filter(Boolean).join(", ") : typeof value === "object" ? JSON.stringify(value) : String(value);
  if (!text.trim()) return;
  lines.push(`${label}: ${text}`);
}
function friendlyLabel(input) {
  return input.replace(/^cf:/, "").replace(/_/g, " ").replace(/([a-z])([A-Z])/g, (_, a, b) => `${a} ${b}`).replace(/\b\w/g, (char) => char.toUpperCase());
}
function appendCustomFieldLines(lines, customFields, prefix) {
  for (const [key, value] of Object.entries(customFields)) {
    if (value === null || value === void 0) continue;
    const label = prefix ? `${prefix} ${friendlyLabel(key)}` : friendlyLabel(key);
    appendLine(lines, label, value);
  }
}
function pickValue(source, ...keys) {
  if (!source) return void 0;
  for (const key of keys) {
    if (key in source && source[key] != null) return source[key];
  }
  return void 0;
}
function pickString(...candidates) {
  for (const candidate of candidates) {
    if (typeof candidate === "string" && candidate.trim().length) {
      return candidate.trim();
    }
  }
  return null;
}
function pickLabel(...candidates) {
  for (const candidate of candidates) {
    if (candidate === null || candidate === void 0) continue;
    const value = typeof candidate === "string" ? candidate : String(candidate);
    const trimmed = value.trim();
    if (trimmed.length) return trimmed;
  }
  return null;
}
function appendCustomerEntityLines(lines, entity, contactLabel = "Customer") {
  if (!entity) return;
  appendLine(lines, "Customer", pickValue(entity, "display_name", "displayName") ?? entity.id);
  appendLine(lines, `${contactLabel} email`, pickValue(entity, "primary_email", "primaryEmail"));
  appendLine(lines, `${contactLabel} phone`, pickValue(entity, "primary_phone", "primaryPhone"));
  appendLine(lines, "Lifecycle stage", pickValue(entity, "lifecycle_stage", "lifecycleStage"));
  appendLine(lines, "Status", pickValue(entity, "status"));
}
function ensureFallbackLines(lines, record, options = {}) {
  if (lines.length) return;
  const excluded = /* @__PURE__ */ new Set(["tenant_id", "organization_id", "created_at", "updated_at", "deleted_at"]);
  for (const [key, value] of Object.entries(record)) {
    if (value === null || value === void 0) continue;
    if (excluded.has(key)) continue;
    if (key === "id") continue;
    appendLine(lines, friendlyLabel(key), value);
  }
  if (!lines.length && options.includeId !== false) {
    const fallbackId = record.id ?? record.entity_id ?? record.customer_entity_id ?? record.entityId ?? record.customerEntityId ?? null;
    if (fallbackId) {
      appendLine(lines, "Record ID", fallbackId);
    }
  }
}
function resolvePersonPresenter(record, entity, customFields) {
  const fallbackEntityId = resolveCustomerEntityId(record);
  const firstName = record.first_name ?? record.firstName ?? customFields.first_name ?? customFields.firstName ?? "";
  const lastName = record.last_name ?? record.lastName ?? customFields.last_name ?? customFields.lastName ?? "";
  const nameParts = [firstName, lastName].filter(Boolean).join(" ");
  const title = pickValue(entity, "display_name", "displayName") ?? record.preferred_name ?? record.preferredName ?? (nameParts.length ? nameParts : void 0) ?? fallbackEntityId ?? record.id ?? "Person";
  const subtitlePieces = [];
  const jobTitle = record.job_title ?? record.jobTitle ?? customFields.job_title ?? customFields.jobTitle;
  if (jobTitle) subtitlePieces.push(String(jobTitle));
  const department = record.department ?? customFields.department;
  if (department) subtitlePieces.push(String(department));
  const primaryEmail = pickValue(entity, "primary_email", "primaryEmail");
  if (primaryEmail) subtitlePieces.push(String(primaryEmail));
  const primaryPhone = pickValue(entity, "primary_phone", "primaryPhone");
  if (primaryPhone) subtitlePieces.push(String(primaryPhone));
  const summary = snippet(
    pickValue(entity, "description") ?? customFields.summary ?? customFields.description
  );
  if (summary) subtitlePieces.push(summary);
  return {
    title: String(title),
    subtitle: subtitlePieces.length ? subtitlePieces.join(" \xB7 ") : void 0,
    icon: "user",
    badge: pickValue(entity, "display_name", "displayName") ? "Person" : void 0
  };
}
function resolveCompanyPresenter(record, entity, customFields) {
  const fallbackEntityId = resolveCustomerEntityId(record);
  const title = pickValue(entity, "display_name", "displayName") ?? customFields.display_name ?? customFields.displayName ?? record.brand_name ?? record.legal_name ?? record.domain ?? record.brandName ?? record.legalName ?? (entity?.id && entity?.display_name ? entity.display_name : void 0) ?? fallbackEntityId ?? record.id ?? "Company";
  const subtitlePieces = [];
  const industry = record.industry;
  if (industry) subtitlePieces.push(String(industry));
  const sizeBucket = record.size_bucket ?? record.sizeBucket;
  if (sizeBucket) subtitlePieces.push(String(sizeBucket));
  if (entity) {
    const primaryEmail = pickValue(entity, "primary_email", "primaryEmail");
    if (primaryEmail) subtitlePieces.push(String(primaryEmail));
  }
  const summary = snippet(
    pickValue(entity, "description") ?? customFields.summary ?? customFields.description ?? record.summary ?? record.description
  );
  if (summary) subtitlePieces.push(summary);
  if (!entity && (!title || title === fallbackEntityId)) {
    logger.warn("Missing customer entity during company presenter build", {
      component: "search",
      recordId: record.id ?? null,
      entityId: fallbackEntityId,
      recordKeys: Object.keys(record)
    });
  }
  return {
    title: String(title),
    subtitle: subtitlePieces.length ? subtitlePieces.join(" \xB7 ") : void 0,
    icon: "building",
    badge: pickValue(entity, "display_name", "displayName") ? "Company" : void 0
  };
}
function logMissingPresenterTitle(kind, record, entity, presenter) {
  const fallbackId = record.id ?? record.entity_id ?? resolveCustomerEntityId(record);
  if (!fallbackId) return;
  if (presenter.title && presenter.title !== String(fallbackId)) return;
  logger.warn("Presenter fell back to record id", {
    component: "search",
    kind,
    recordId: fallbackId,
    entityId: resolveCustomerEntityId(record),
    hasEntityDisplayName: entity?.display_name != null
  });
}
const searchConfig = {
  entities: [
    // =========================================================================
    // Person Profile
    // =========================================================================
    {
      entityId: "customers:customer_person_profile",
      enabled: true,
      priority: 10,
      buildSource: async (ctx) => {
        assertTenantContext(ctx);
        const lines = [];
        const record = ctx.record;
        appendLine(lines, "Preferred name", record.preferred_name ?? record.preferredName ?? ctx.customFields.preferred_name);
        appendLine(lines, "First name", record.first_name ?? record.firstName ?? ctx.customFields.first_name);
        appendLine(lines, "Last name", record.last_name ?? record.lastName ?? ctx.customFields.last_name);
        appendLine(lines, "Job title", record.job_title ?? record.jobTitle ?? ctx.customFields.job_title);
        appendLine(lines, "Department", record.department ?? record.department_name ?? record.departmentName ?? ctx.customFields.department);
        appendLine(lines, "Seniority", record.seniority ?? record.seniority_level ?? record.seniorityLevel ?? ctx.customFields.seniority);
        appendLine(lines, "Timezone", record.timezone ?? record.time_zone ?? record.timeZone ?? ctx.customFields.timezone);
        appendLine(lines, "LinkedIn", record.linked_in_url ?? record.linkedInUrl ?? ctx.customFields.linked_in_url);
        appendLine(lines, "Twitter", record.twitter_url ?? record.twitterUrl ?? ctx.customFields.twitter_url);
        const { entity, entityId, profileCustomFields, entityCustomFields, entityOnlyCustomFields } = await hydrateProfileContext(ctx, "person");
        appendCustomFieldLines(lines, profileCustomFields, "Person custom");
        if (Object.keys(entityOnlyCustomFields).length) {
          appendCustomFieldLines(lines, entityOnlyCustomFields, "Customer custom");
        }
        if (!entity) {
          logger.warn("Failed to load customer entity for person profile", {
            component: "search",
            recordId: record.id,
            entityId,
            recordKeys: Object.keys(record)
          });
        }
        appendCustomerEntityLines(lines, entity, "Customer");
        ensureFallbackLines(lines, record);
        if (!lines.length) return null;
        if (!entityId) {
          logger.warn("Person profile missing entity id", {
            component: "search",
            recordId: record.id,
            recordKeys: Object.keys(record)
          });
        }
        const presenter = resolvePersonPresenter(record, entity, ctx.customFields);
        logMissingPresenterTitle("person", record, entity, presenter);
        const presenterLabel = pickLabel(presenter.title) ?? "Open person";
        const links = [];
        if (entityId) {
          const href = buildCustomerUrl("person", entityId);
          if (href) {
            links.push({ href, label: presenterLabel, kind: "primary" });
          }
        }
        return {
          text: lines,
          presenter,
          links,
          checksumSource: {
            record: ctx.record,
            customFields: profileCustomFields,
            entity,
            entityCustomFields
          }
        };
      },
      formatResult: async (ctx) => {
        assertTenantContext(ctx);
        const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record));
        return resolvePersonPresenter(ctx.record, entity, ctx.customFields);
      },
      resolveUrl: async (ctx) => {
        const entityId = resolveCustomerEntityId(ctx.record);
        return buildCustomerUrl("person", entityId);
      },
      resolveLinks: async (ctx) => {
        const entityId = resolveCustomerEntityId(ctx.record);
        if (!entityId) return null;
        const href = buildCustomerUrl("person", entityId);
        if (!href) return null;
        return [{ href: `${href}/edit`, label: "Edit", kind: "secondary" }];
      },
      fieldPolicy: {
        searchable: [
          "preferred_name",
          "first_name",
          "last_name",
          "job_title",
          "department",
          "seniority",
          "timezone",
          "linked_in_url",
          "twitter_url"
        ],
        hashOnly: ["primary_email", "primary_phone", "personal_email"],
        excluded: ["date_of_birth", "government_id", "ssn", "tax_id"]
      },
      aclFeatures: ["customers.people.view"]
    },
    // =========================================================================
    // Company Profile
    // =========================================================================
    {
      entityId: "customers:customer_company_profile",
      enabled: true,
      priority: 10,
      buildSource: async (ctx) => {
        assertTenantContext(ctx);
        const lines = [];
        const record = ctx.record;
        appendLine(lines, "Legal name", record.legal_name ?? record.legalName ?? ctx.customFields.legal_name);
        appendLine(lines, "Brand name", record.brand_name ?? record.brandName ?? ctx.customFields.brand_name);
        appendLine(lines, "Domain", record.domain ?? record.website_domain ?? record.websiteDomain ?? ctx.customFields.domain);
        appendLine(lines, "Website", record.website_url ?? record.websiteUrl ?? ctx.customFields.website_url);
        appendLine(lines, "Industry", record.industry ?? ctx.customFields.industry);
        appendLine(lines, "Company size", record.size_bucket ?? record.sizeBucket ?? ctx.customFields.size_bucket);
        appendLine(lines, "Annual revenue", record.annual_revenue ?? record.annualRevenue ?? ctx.customFields.annual_revenue);
        const { entity, entityId, profileCustomFields, entityCustomFields, entityOnlyCustomFields } = await hydrateProfileContext(ctx, "company");
        appendCustomFieldLines(lines, profileCustomFields, "Company custom");
        if (Object.keys(entityOnlyCustomFields).length) {
          appendCustomFieldLines(lines, entityOnlyCustomFields, "Customer custom");
        }
        appendCustomerEntityLines(lines, entity, "Primary");
        ensureFallbackLines(lines, record);
        if (!lines.length) return null;
        const presenter = resolveCompanyPresenter(record, entity, ctx.customFields);
        logMissingPresenterTitle("company", record, entity, presenter);
        const primaryLabel = pickLabel(presenter.title) ?? "Open company";
        const links = [];
        if (entityId) {
          const href = buildCustomerUrl("company", entityId);
          if (href) {
            links.push({ href, label: primaryLabel, kind: "primary" });
          }
        }
        return {
          text: lines,
          presenter,
          links,
          checksumSource: {
            record: ctx.record,
            customFields: profileCustomFields,
            entity,
            entityCustomFields
          }
        };
      },
      formatResult: async (ctx) => {
        assertTenantContext(ctx);
        const entity = await getCustomerEntity(ctx, resolveCustomerEntityId(ctx.record));
        return resolveCompanyPresenter(ctx.record, entity, ctx.customFields);
      },
      resolveUrl: async (ctx) => {
        const entityId = resolveCustomerEntityId(ctx.record);
        return buildCustomerUrl("company", entityId);
      },
      resolveLinks: async (ctx) => {
        const entityId = resolveCustomerEntityId(ctx.record);
        if (!entityId) return null;
        const href = buildCustomerUrl("company", entityId);
        if (!href) return null;
        return [{ href: `${href}/edit`, label: "Edit", kind: "secondary" }];
      },
      fieldPolicy: {
        searchable: [
          "legal_name",
          "brand_name",
          "display_name",
          "domain",
          "website_url",
          "industry",
          "size_bucket",
          "description"
        ],
        hashOnly: ["tax_id", "registration_number"],
        excluded: ["bank_account", "billing_info", "credit_info"]
      },
      aclFeatures: ["customers.companies.view"]
    },
    // =========================================================================
    // Customer Comment
    // =========================================================================
    {
      entityId: "customers:customer_comment",
      enabled: true,
      priority: 6,
      buildSource: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const lines = [];
        if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`);
        lines.push(`Note: ${ctx.record.body ?? ""}`);
        if (ctx.record.appearance_icon) lines.push(`Icon: ${ctx.record.appearance_icon}`);
        if (ctx.record.appearance_color) lines.push(`Color: ${ctx.record.appearance_color}`);
        const presenter = parent?.display_name ? {
          title: parent.display_name,
          subtitle: snippet(ctx.record.body),
          icon: parent.kind === "person" ? "user" : "building"
        } : void 0;
        return {
          text: lines,
          presenter,
          checksumSource: {
            body: ctx.record.body,
            entityId: ctx.record.entity_id ?? null,
            updatedAt: ctx.record.updated_at ?? ctx.record.updatedAt ?? null
          }
        };
      },
      formatResult: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const title = parent?.display_name ?? "Customer note";
        return {
          title,
          subtitle: snippet(ctx.record.body),
          icon: "sticky-note"
        };
      },
      resolveUrl: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const base = buildCustomerUrl(parent?.kind ?? null, parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId);
        return base ? `${base}#notes` : null;
      },
      resolveLinks: async (ctx) => {
        assertTenantContext(ctx);
        const links = [];
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const parentUrl = buildCustomerUrl(parent?.kind ?? null, parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId);
        if (parentUrl) {
          links.push({ href: parentUrl, label: parent?.display_name ?? "View customer", kind: "primary" });
        }
        if (ctx.record.deal_id) {
          const dealUrl = `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id)}`;
          links.push({ href: dealUrl, label: "Open deal", kind: "secondary" });
        }
        return links.length ? links : null;
      },
      fieldPolicy: {
        searchable: ["body"],
        hashOnly: [],
        excluded: []
      },
      aclFeatures: ["customers.activities.view"]
    },
    // =========================================================================
    // Customer Deal
    // =========================================================================
    {
      entityId: "customers:customer_deal",
      enabled: true,
      priority: 8,
      buildSource: async (ctx) => {
        const lines = [];
        const record = ctx.record;
        appendLine(lines, "Title", record.title);
        appendLine(lines, "Stage", record.pipeline_stage);
        appendLine(lines, "Status", record.status);
        appendLine(lines, "Source", record.source);
        const value = formatDealValue(record);
        if (value) appendLine(lines, "Value", value);
        if (!lines.length) return null;
        const subtitleParts = [];
        if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage));
        if (record.status) subtitleParts.push(String(record.status));
        if (value) subtitleParts.push(value);
        return {
          text: lines,
          presenter: {
            title: String(record.title ?? "Deal"),
            subtitle: subtitleParts.join(" \xB7 ") || void 0,
            icon: "briefcase",
            badge: "Deal"
          },
          checksumSource: {
            title: record.title,
            status: record.status,
            stage: record.pipeline_stage,
            value
          }
        };
      },
      formatResult: async (ctx) => {
        const { record } = ctx;
        const title = pickString(record.title, "Deal");
        const subtitleParts = [];
        if (record.pipeline_stage) subtitleParts.push(String(record.pipeline_stage));
        if (record.status) subtitleParts.push(String(record.status));
        const amount = record.value_amount ?? record.valueAmount;
        const currency = record.value_currency ?? record.valueCurrency;
        if (amount) {
          subtitleParts.push(currency ? `${amount} ${currency}` : String(amount));
        }
        return {
          title: title ?? "Deal",
          subtitle: subtitleParts.length ? subtitleParts.join(" \xB7 ") : void 0,
          icon: "briefcase",
          badge: "Deal"
        };
      },
      resolveUrl: async (ctx) => {
        const id = ctx.record.id;
        if (!id) return null;
        return `/backend/customers/deals/${encodeURIComponent(String(id))}`;
      },
      resolveLinks: async (ctx) => {
        const id = ctx.record.id;
        if (!id) return null;
        return [
          {
            href: `/backend/customers/deals/${encodeURIComponent(String(id))}/edit`,
            label: "Edit",
            kind: "secondary"
          }
        ];
      },
      fieldPolicy: {
        searchable: ["title", "description", "pipeline_stage", "status", "source"],
        hashOnly: [],
        excluded: ["value_amount", "value_currency"]
      },
      aclFeatures: ["customers.deals.view"]
    },
    // =========================================================================
    // Customer Activity
    // =========================================================================
    {
      entityId: "customers:customer_activity",
      enabled: true,
      priority: 5,
      buildSource: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const lines = [];
        if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`);
        if (ctx.record.activity_type) lines.push(`Type: ${ctx.record.activity_type}`);
        if (ctx.record.subject) lines.push(`Subject: ${ctx.record.subject}`);
        if (ctx.record.body) lines.push(`Body: ${ctx.record.body}`);
        const presenter = {
          title: ctx.record.subject ? String(ctx.record.subject) : `Activity: ${ctx.record.activity_type ?? "update"}`,
          subtitle: parent?.display_name ?? snippet(ctx.record.body),
          icon: "bolt"
        };
        return {
          text: lines,
          presenter,
          checksumSource: {
            subject: ctx.record.subject,
            body: ctx.record.body,
            entityId: ctx.record.entity_id ?? null,
            updatedAt: ctx.record.updated_at ?? ctx.record.updatedAt ?? null
          }
        };
      },
      formatResult: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        return {
          title: ctx.record.subject ? String(ctx.record.subject) : `Activity: ${ctx.record.activity_type ?? "update"}`,
          subtitle: parent?.display_name ?? snippet(ctx.record.body),
          icon: "bolt",
          badge: "Activity"
        };
      },
      resolveUrl: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const base = buildCustomerUrl(parent?.kind ?? null, parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId);
        return base ? `${base}#activity-${ctx.record.id ?? ctx.record.activity_id ?? ""}` : null;
      },
      resolveLinks: async (ctx) => {
        const links = [];
        if (ctx.record.deal_id) {
          links.push({
            href: `/backend/customers/deals/${encodeURIComponent(ctx.record.deal_id)}`,
            label: "Open deal",
            kind: "secondary"
          });
        }
        return links.length ? links : null;
      },
      fieldPolicy: {
        searchable: ["subject", "body", "activity_type"],
        hashOnly: [],
        excluded: []
      },
      aclFeatures: ["customers.activities.view"]
    },
    // =========================================================================
    // Customer Todo Link
    // =========================================================================
    {
      entityId: "customers:customer_todo_link",
      enabled: true,
      priority: 4,
      buildSource: async (ctx) => {
        assertTenantContext(ctx);
        const todo = await getLinkedTodo(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const lines = [];
        if (todo?.title) lines.push(`Todo: ${todo.title}`);
        if (todo?.is_done !== void 0) lines.push(`Status: ${todo.is_done ? "Done" : "Open"}`);
        if (parent?.display_name) lines.push(`Customer: ${parent.display_name}`);
        if (!lines.length) return null;
        return {
          text: lines,
          presenter: todo?.title ? { title: todo.title, subtitle: parent?.display_name, icon: "check-square" } : void 0,
          checksumSource: {
            todoId: ctx.record.todo_id ?? ctx.record.todoId,
            todoSource: ctx.record.todo_source ?? ctx.record.todoSource,
            entityId: ctx.record.entity_id ?? ctx.record.entityId
          }
        };
      },
      formatResult: async (ctx) => {
        assertTenantContext(ctx);
        const todo = await getLinkedTodo(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        return {
          title: todo?.title ?? "Customer task",
          subtitle: parent?.display_name,
          icon: "check-square"
        };
      },
      resolveUrl: async (ctx) => {
        assertTenantContext(ctx);
        const parent = await getCustomerEntity(ctx, ctx.record.entity_id ?? ctx.record.entityId);
        const base = buildCustomerUrl(parent?.kind ?? null, parent?.id ?? ctx.record.entity_id ?? ctx.record.entityId);
        return base ? `${base}#tasks` : null;
      },
      resolveLinks: async (ctx) => {
        const todoId = ctx.record.todo_id ?? ctx.record.todoId;
        if (!todoId) return null;
        return [{
          href: `/backend/todos/${encodeURIComponent(todoId)}/edit`,
          label: "Open todo",
          kind: "secondary"
        }];
      },
      fieldPolicy: {
        searchable: [],
        hashOnly: [],
        excluded: []
      },
      aclFeatures: ["customers.activities.view"]
    }
  ]
};
var search_default = searchConfig;
const config = searchConfig;
export {
  config,
  search_default as default,
  searchConfig
};
//# sourceMappingURL=search.js.map
