import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { extractPhoneDigits, validatePhoneNumber } from "@open-mercato/shared/lib/phone";
import { SyncMapping } from "../../../data_sync/data/entities.js";
import { CustomerAddress, CustomerEntity } from "../../../customers/data/entities.js";
import { Attachment } from "../../../attachments/data/entities.js";
import { CustomFieldDef } from "../../../entities/data/entities.js";
import { SyncExcelUpload } from "../../data/entities.js";
import { parseCsvDocument } from "../parser.js";
import { readSyncExcelUploadBuffer } from "../upload-storage.js";
import { E } from "../../../../generated/entities.ids.generated.js";
const CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES = [
  E.customers.customer_entity,
  E.customers.customer_person_profile,
  E.customers.customer_address
];
function normalizeOptionalString(value) {
  if (typeof value !== "string") return null;
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : null;
}
function normalizeEmail(value) {
  const normalized = normalizeOptionalString(value);
  return normalized ? normalized.toLowerCase() : null;
}
const COUNTRY_DIAL_CODES = {
  canada: "1",
  england: "44",
  greatbritain: "44",
  poland: "48",
  scotland: "44",
  uk: "44",
  unitedkingdom: "44",
  unitedstates: "1",
  unitedstatesofamerica: "1",
  usa: "1",
  wales: "44"
};
function normalizeCountryKey(value) {
  const normalized = normalizeOptionalString(value);
  if (!normalized) return null;
  return normalized.toLowerCase().replace(/[^a-z]/g, "");
}
function resolveCountryDialCode(row) {
  const countryCandidates = [
    row.Country,
    row.country,
    row["Country/Region"],
    row["country/region"]
  ];
  for (const candidate of countryCandidates) {
    const countryKey = normalizeCountryKey(candidate);
    if (!countryKey) continue;
    const dialCode = COUNTRY_DIAL_CODES[countryKey];
    if (dialCode) return dialCode;
  }
  return null;
}
function stripPhoneExtension(value) {
  return value.replace(/\s*(ext\.?|extension|x)\s*\d+$/i, "").replace(/^\+\s+/, "+").replace(/\s+/g, " ").trim();
}
function normalizeImportedPhone(value, row) {
  const normalized = normalizeOptionalString(value);
  if (!normalized) return null;
  const directValidation = validatePhoneNumber(normalized);
  if (directValidation.valid) {
    return directValidation.normalized;
  }
  const sanitized = stripPhoneExtension(normalized);
  const sanitizedValidation = validatePhoneNumber(sanitized);
  if (sanitizedValidation.valid) {
    return sanitizedValidation.normalized;
  }
  const digits = extractPhoneDigits(sanitized);
  if (!digits) return null;
  if (digits.length >= 9 && digits.length <= 15 && sanitized.startsWith("00")) {
    const internationalCandidate = `+${digits.slice(2)}`;
    const internationalValidation = validatePhoneNumber(internationalCandidate);
    if (internationalValidation.valid) {
      return internationalValidation.normalized;
    }
  }
  const dialCode = resolveCountryDialCode(row);
  if (!dialCode) return null;
  let nationalDigits = digits;
  if (nationalDigits.startsWith(dialCode)) {
    nationalDigits = nationalDigits.slice(dialCode.length);
  } else {
    nationalDigits = nationalDigits.replace(/^0+/, "");
  }
  if (!nationalDigits) return null;
  const localizedCandidate = `+${dialCode}${nationalDigits}`;
  const localizedValidation = validatePhoneNumber(localizedCandidate);
  return localizedValidation.valid ? localizedValidation.normalized : null;
}
function normalizeOptionalNumber(value) {
  if (typeof value === "number") {
    return Number.isFinite(value) ? value : null;
  }
  if (typeof value !== "string") return null;
  const trimmed = value.trim();
  if (trimmed.length === 0) return null;
  const parsed = Number(trimmed);
  return Number.isFinite(parsed) ? parsed : null;
}
function normalizeCustomFieldDate(value) {
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return null;
  return parsed.toISOString().slice(0, 10);
}
function normalizeCustomFieldBoolean(value) {
  const normalized = value.trim().toLowerCase();
  if (["true", "1", "yes", "y", "t", "tak"].includes(normalized)) return true;
  if (["false", "0", "no", "n", "f", "nie"].includes(normalized)) return false;
  return null;
}
function coerceCustomFieldValue(key, value, definitions) {
  if (typeof value === "string" && value.trim().length === 0) {
    return { ok: true, value: null };
  }
  const definition = definitions.get(key);
  if (!definition) {
    return { ok: true, value: typeof value === "string" ? value.trim() : value };
  }
  if (value === null || value === void 0) {
    return { ok: true, value: null };
  }
  const text = typeof value === "string" ? value.trim() : String(value);
  if (text.length === 0) {
    return { ok: true, value: null };
  }
  const kind = definition.kind.toLowerCase();
  if (kind === "boolean") {
    const booleanValue = normalizeCustomFieldBoolean(text);
    if (booleanValue === null) {
      return { ok: false, error: `Custom field "${key}" expects a boolean value.` };
    }
    return { ok: true, value: booleanValue };
  }
  if (kind === "integer") {
    const numberValue = Number(text);
    if (!Number.isInteger(numberValue)) {
      return { ok: false, error: `Custom field "${key}" expects an integer value.` };
    }
    return { ok: true, value: numberValue };
  }
  if (kind === "float" || kind === "currency" || kind === "number") {
    const numberValue = Number(text);
    if (!Number.isFinite(numberValue)) {
      return { ok: false, error: `Custom field "${key}" expects a number value.` };
    }
    return { ok: true, value: numberValue };
  }
  if (kind === "date" || kind === "datetime") {
    const dateValue = normalizeCustomFieldDate(text);
    if (!dateValue) {
      return { ok: false, error: `Custom field "${key}" expects a date value.` };
    }
    return { ok: true, value: dateValue };
  }
  return { ok: true, value: text };
}
function coerceCustomFields(values, definitions) {
  const coerced = {};
  for (const [key, value] of Object.entries(values)) {
    const result = coerceCustomFieldValue(key, value, definitions);
    if (!result.ok) return result;
    coerced[key] = result.value;
  }
  return { ok: true, values: coerced };
}
function customFieldDefinitionScopeScore(definition) {
  return (definition.tenantId ? 2 : 0) + (definition.organizationId ? 1 : 0);
}
function customFieldDefinitionUpdatedAt(definition) {
  if (!definition.updatedAt) return 0;
  const value = definition.updatedAt instanceof Date ? definition.updatedAt.getTime() : new Date(definition.updatedAt).getTime();
  return Number.isFinite(value) ? value : 0;
}
function preferCustomFieldDefinition(current, candidate) {
  if (!current) return true;
  const candidateScore = customFieldDefinitionScopeScore(candidate);
  const currentScore = customFieldDefinitionScopeScore(current);
  if (candidateScore !== currentScore) return candidateScore > currentScore;
  return customFieldDefinitionUpdatedAt(candidate) >= customFieldDefinitionUpdatedAt(current);
}
async function loadImportCustomFieldDefinitions(em, scope) {
  const definitions = await findWithDecryption(
    em,
    CustomFieldDef,
    {
      entityId: { $in: [E.customers.customer_entity, E.customers.customer_person_profile] },
      deletedAt: null,
      isActive: true,
      $and: [
        { $or: [{ tenantId: scope.tenantId }, { tenantId: null }] },
        { $or: [{ organizationId: scope.organizationId }, { organizationId: null }] }
      ]
    },
    void 0,
    scope
  );
  const byKey = /* @__PURE__ */ new Map();
  for (const definition of definitions) {
    const candidate = {
      key: definition.key,
      kind: definition.kind,
      entityId: definition.entityId,
      organizationId: definition.organizationId ?? null,
      tenantId: definition.tenantId ?? null,
      updatedAt: definition.updatedAt ?? null
    };
    if (preferCustomFieldDefinition(byKey.get(candidate.key), candidate)) {
      byKey.set(candidate.key, candidate);
    }
  }
  return byKey;
}
function buildCommandContext(container, scope) {
  return {
    container,
    auth: null,
    organizationScope: {
      selectedId: scope.organizationId,
      filterIds: [scope.organizationId],
      allowedIds: [scope.organizationId],
      tenantId: scope.tenantId
    },
    selectedOrganizationId: scope.organizationId,
    organizationIds: [scope.organizationId]
  };
}
function createCursor(uploadId, offset) {
  return JSON.stringify({
    uploadId,
    offset
  });
}
function parseCursor(value) {
  if (!value) return null;
  try {
    const parsed = JSON.parse(value);
    if (!parsed || typeof parsed !== "object") return null;
    if (typeof parsed.uploadId !== "string" || parsed.uploadId.trim().length === 0) return null;
    if (typeof parsed.offset !== "number" || !Number.isFinite(parsed.offset) || parsed.offset < 0) return null;
    return {
      uploadId: parsed.uploadId,
      offset: parsed.offset
    };
  } catch {
    return null;
  }
}
function mapRowValues(row, fields) {
  const values = {};
  const customFields = {};
  const addressValues = {};
  for (const field of fields) {
    if (field.mappingKind === "ignore") continue;
    const rawValue = row[field.externalField];
    if (rawValue === void 0 || rawValue === null) continue;
    if (field.mappingKind === "custom_field" || field.localField.startsWith("cf:")) {
      const customFieldKey = field.localField.startsWith("cf:") ? field.localField.slice(3) : field.localField;
      if (customFieldKey.trim().length > 0) {
        customFields[customFieldKey] = rawValue;
      }
      continue;
    }
    if (field.localField === "person.externalId") {
      values.externalId = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.firstName") {
      values.firstName = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.lastName") {
      values.lastName = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.displayName") {
      values.displayName = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.primaryEmail") {
      values.primaryEmail = normalizeEmail(rawValue);
      continue;
    }
    if (field.localField === "person.primaryPhone") {
      values.primaryPhone = normalizeImportedPhone(rawValue, row);
      continue;
    }
    if (field.localField === "person.jobTitle") {
      values.jobTitle = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.status") {
      values.status = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.source") {
      values.source = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "person.description") {
      values.description = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.name") {
      addressValues.name = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.purpose") {
      addressValues.purpose = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.companyName") {
      addressValues.companyName = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.addressLine1") {
      addressValues.addressLine1 = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.addressLine2") {
      addressValues.addressLine2 = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.buildingNumber") {
      addressValues.buildingNumber = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.flatNumber") {
      addressValues.flatNumber = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.city") {
      addressValues.city = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.region") {
      addressValues.region = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.postalCode") {
      addressValues.postalCode = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.country") {
      addressValues.country = normalizeOptionalString(rawValue);
      continue;
    }
    if (field.localField === "address.latitude") {
      addressValues.latitude = normalizeOptionalNumber(rawValue);
      continue;
    }
    if (field.localField === "address.longitude") {
      addressValues.longitude = normalizeOptionalNumber(rawValue);
    }
  }
  return {
    values,
    customFields,
    addressValues
  };
}
function derivePersonNames(values) {
  const firstName = values.firstName ?? null;
  const lastName = values.lastName ?? null;
  const explicitDisplayName = values.displayName ?? null;
  if (firstName && lastName) {
    return {
      firstName,
      lastName,
      displayName: explicitDisplayName ?? `${firstName} ${lastName}`.trim()
    };
  }
  if (explicitDisplayName) {
    const parts = explicitDisplayName.split(/\s+/).filter((part) => part.length > 0);
    if (parts.length >= 2) {
      return {
        firstName: firstName ?? parts.slice(0, -1).join(" "),
        lastName: lastName ?? parts.at(-1) ?? explicitDisplayName,
        displayName: explicitDisplayName
      };
    }
    return {
      firstName: firstName ?? explicitDisplayName,
      lastName: lastName ?? explicitDisplayName,
      displayName: explicitDisplayName
    };
  }
  return null;
}
function buildPersonPayload(row, mapping, scope) {
  const { values, customFields, addressValues } = mapRowValues(row, mapping.fields);
  const derivedNames = derivePersonNames(values);
  const sourceIdentifier = values.externalId ?? values.primaryEmail ?? values.displayName ?? null;
  const updateInput = {
    organizationId: scope.organizationId,
    tenantId: scope.tenantId
  };
  if (values.primaryEmail) updateInput.primaryEmail = values.primaryEmail;
  if (values.primaryPhone) updateInput.primaryPhone = values.primaryPhone;
  if (values.jobTitle) updateInput.jobTitle = values.jobTitle;
  if (values.status) updateInput.status = values.status;
  if (values.source) updateInput.source = values.source;
  if (values.description) updateInput.description = values.description;
  if (derivedNames?.firstName) updateInput.firstName = derivedNames.firstName;
  if (derivedNames?.lastName) updateInput.lastName = derivedNames.lastName;
  if (derivedNames?.displayName) updateInput.displayName = derivedNames.displayName;
  if (!derivedNames) {
    return {
      values,
      customFields,
      addressValues,
      createInput: null,
      updateInput,
      sourceIdentifier
    };
  }
  return {
    values,
    customFields,
    addressValues,
    createInput: {
      organizationId: scope.organizationId,
      tenantId: scope.tenantId,
      firstName: derivedNames.firstName,
      lastName: derivedNames.lastName,
      displayName: derivedNames.displayName,
      ...values.primaryEmail ? { primaryEmail: values.primaryEmail } : {},
      ...values.primaryPhone ? { primaryPhone: values.primaryPhone } : {},
      ...values.jobTitle ? { jobTitle: values.jobTitle } : {},
      ...values.status ? { status: values.status } : {},
      ...values.source ? { source: values.source } : {},
      ...values.description ? { description: values.description } : {}
    },
    updateInput,
    sourceIdentifier
  };
}
function hasAddressValues(addressValues) {
  return Object.values(addressValues).some((value) => value !== null && value !== void 0);
}
function buildAddressCreateInput(addressValues, entityId, scope) {
  if (!addressValues.addressLine1) return null;
  return {
    organizationId: scope.organizationId,
    tenantId: scope.tenantId,
    entityId,
    addressLine1: addressValues.addressLine1,
    isPrimary: true,
    ...addressValues.name ? { name: addressValues.name } : {},
    ...addressValues.purpose ? { purpose: addressValues.purpose } : {},
    ...addressValues.companyName ? { companyName: addressValues.companyName } : {},
    ...addressValues.addressLine2 ? { addressLine2: addressValues.addressLine2 } : {},
    ...addressValues.buildingNumber ? { buildingNumber: addressValues.buildingNumber } : {},
    ...addressValues.flatNumber ? { flatNumber: addressValues.flatNumber } : {},
    ...addressValues.city ? { city: addressValues.city } : {},
    ...addressValues.region ? { region: addressValues.region } : {},
    ...addressValues.postalCode ? { postalCode: addressValues.postalCode } : {},
    ...addressValues.country ? { country: addressValues.country } : {},
    ...addressValues.latitude !== null && addressValues.latitude !== void 0 ? { latitude: addressValues.latitude } : {},
    ...addressValues.longitude !== null && addressValues.longitude !== void 0 ? { longitude: addressValues.longitude } : {}
  };
}
async function upsertPrimaryAddress(params) {
  if (!hasAddressValues(params.addressValues)) return;
  if (!params.addressValues.addressLine1) return;
  const [existingPrimaryAddress] = await findWithDecryption(
    params.em,
    CustomerAddress,
    {
      entity: params.entityId,
      organizationId: params.scope.organizationId,
      tenantId: params.scope.tenantId,
      isPrimary: true
    },
    {
      orderBy: {
        createdAt: "asc"
      },
      limit: 1
    },
    params.scope
  );
  if (existingPrimaryAddress) {
    await params.commandBus.execute("customers.addresses.update", {
      input: {
        id: existingPrimaryAddress.id,
        isPrimary: true,
        ...params.addressValues.name ? { name: params.addressValues.name } : {},
        ...params.addressValues.purpose ? { purpose: params.addressValues.purpose } : {},
        ...params.addressValues.companyName ? { companyName: params.addressValues.companyName } : {},
        ...params.addressValues.addressLine1 ? { addressLine1: params.addressValues.addressLine1 } : {},
        ...params.addressValues.addressLine2 ? { addressLine2: params.addressValues.addressLine2 } : {},
        ...params.addressValues.buildingNumber ? { buildingNumber: params.addressValues.buildingNumber } : {},
        ...params.addressValues.flatNumber ? { flatNumber: params.addressValues.flatNumber } : {},
        ...params.addressValues.city ? { city: params.addressValues.city } : {},
        ...params.addressValues.region ? { region: params.addressValues.region } : {},
        ...params.addressValues.postalCode ? { postalCode: params.addressValues.postalCode } : {},
        ...params.addressValues.country ? { country: params.addressValues.country } : {},
        ...params.addressValues.latitude !== null && params.addressValues.latitude !== void 0 ? { latitude: params.addressValues.latitude } : {},
        ...params.addressValues.longitude !== null && params.addressValues.longitude !== void 0 ? { longitude: params.addressValues.longitude } : {}
      },
      ctx: params.commandContext
    });
    return;
  }
  const createInput = buildAddressCreateInput(params.addressValues, params.entityId, params.scope);
  if (!createInput) return;
  await params.commandBus.execute("customers.addresses.create", {
    input: createInput,
    ctx: params.commandContext
  });
}
async function loadStoredMapping(em, entityType, scope) {
  const stored = await findOneWithDecryption(
    em,
    SyncMapping,
    {
      integrationId: "sync_excel",
      entityType,
      organizationId: scope.organizationId,
      tenantId: scope.tenantId
    },
    void 0,
    scope
  );
  if (stored?.mapping && typeof stored.mapping === "object") {
    return stored.mapping;
  }
  return {
    entityType,
    fields: [],
    matchStrategy: "custom"
  };
}
async function resolveUpload(em, runId, cursor, scope) {
  if (runId) {
    const uploadByRun = await findOneWithDecryption(
      em,
      SyncExcelUpload,
      {
        syncRunId: runId,
        organizationId: scope.organizationId,
        tenantId: scope.tenantId
      },
      void 0,
      scope
    );
    if (uploadByRun) return uploadByRun;
  }
  if (cursor?.uploadId) {
    return findOneWithDecryption(
      em,
      SyncExcelUpload,
      {
        id: cursor.uploadId,
        organizationId: scope.organizationId,
        tenantId: scope.tenantId
      },
      void 0,
      scope
    );
  }
  return null;
}
async function resolveExistingPersonId(params) {
  if (params.externalId) {
    const mappedLocalId = await params.externalIdMappingService.lookupLocalId(
      "sync_excel",
      "customers.person",
      params.externalId,
      params.scope
    );
    if (mappedLocalId) return mappedLocalId;
  }
  if (!params.email) return null;
  return params.emailDedupeIndex.get(params.email) ?? null;
}
async function buildEmailDedupeIndex(params) {
  const emails = /* @__PURE__ */ new Set();
  for (const row of params.rows) {
    const rowValues = mapRowValues(row, params.mapping.fields);
    const email = rowValues.values.primaryEmail;
    if (email) emails.add(email);
  }
  if (emails.size === 0) return /* @__PURE__ */ new Map();
  const candidates = await findWithDecryption(
    params.em,
    CustomerEntity,
    {
      kind: "person",
      organizationId: params.scope.organizationId,
      tenantId: params.scope.tenantId,
      deletedAt: null,
      isActive: true
    },
    {
      orderBy: {
        createdAt: "asc"
      }
    },
    params.scope
  );
  const index = /* @__PURE__ */ new Map();
  for (const candidate of candidates) {
    const email = normalizeEmail(candidate.primaryEmail);
    if (!email || !emails.has(email) || index.has(email)) continue;
    index.set(email, candidate.id);
  }
  return index;
}
function isEmptyRow(row) {
  return !Object.values(row).some((value) => normalizeOptionalString(value));
}
async function processRow(params) {
  if (isEmptyRow(params.row)) {
    return {
      externalId: `row:${params.rowNumber}`,
      action: "skip",
      data: {
        rowNumber: params.rowNumber,
        reason: "empty_row"
      }
    };
  }
  const payload = buildPersonPayload(params.row, params.mapping, params.scope);
  const externalId = payload.values.externalId ?? null;
  const sourceIdentifier = payload.sourceIdentifier ?? `row:${params.rowNumber}`;
  const customFieldResult = coerceCustomFields(payload.customFields, params.customFieldDefinitions);
  if (!customFieldResult.ok) {
    return {
      externalId: externalId ?? sourceIdentifier,
      action: "failed",
      data: {
        rowNumber: params.rowNumber,
        sourceIdentifier,
        errorMessage: customFieldResult.error
      }
    };
  }
  const existingId = await resolveExistingPersonId({
    externalIdMappingService: params.externalIdMappingService,
    externalId,
    email: payload.values.primaryEmail,
    emailDedupeIndex: params.emailDedupeIndex,
    scope: params.scope
  });
  if (!existingId && !payload.createInput) {
    return {
      externalId: externalId ?? sourceIdentifier,
      action: "failed",
      data: {
        rowNumber: params.rowNumber,
        sourceIdentifier,
        errorMessage: "Import row is missing a usable person name mapping."
      }
    };
  }
  try {
    if (existingId) {
      const updateInput = {
        id: existingId,
        ...payload.updateInput,
        ...Object.keys(customFieldResult.values).length > 0 ? { customFields: customFieldResult.values } : {}
      };
      await params.commandBus.execute("customers.people.update", {
        input: updateInput,
        ctx: params.commandContext
      });
      await upsertPrimaryAddress({
        entityId: existingId,
        addressValues: payload.addressValues,
        scope: params.scope,
        commandBus: params.commandBus,
        commandContext: params.commandContext,
        em: params.em
      });
      if (externalId) {
        await params.externalIdMappingService.storeExternalIdMapping(
          "sync_excel",
          "customers.person",
          existingId,
          externalId,
          params.scope
        );
      }
      if (payload.values.primaryEmail && !params.emailDedupeIndex.has(payload.values.primaryEmail)) {
        params.emailDedupeIndex.set(payload.values.primaryEmail, existingId);
      }
      return {
        externalId: externalId ?? sourceIdentifier,
        action: "update",
        data: {
          localId: existingId,
          rowNumber: params.rowNumber,
          sourceIdentifier
        }
      };
    }
    const commandResult = await params.commandBus.execute("customers.people.create", {
      input: {
        ...payload.createInput,
        ...Object.keys(customFieldResult.values).length > 0 ? { customFields: customFieldResult.values } : {}
      },
      ctx: params.commandContext
    });
    await upsertPrimaryAddress({
      entityId: commandResult.result.entityId,
      addressValues: payload.addressValues,
      scope: params.scope,
      commandBus: params.commandBus,
      commandContext: params.commandContext,
      em: params.em
    });
    if (externalId) {
      await params.externalIdMappingService.storeExternalIdMapping(
        "sync_excel",
        "customers.person",
        commandResult.result.entityId,
        externalId,
        params.scope
      );
    }
    if (payload.values.primaryEmail && !params.emailDedupeIndex.has(payload.values.primaryEmail)) {
      params.emailDedupeIndex.set(payload.values.primaryEmail, commandResult.result.entityId);
    }
    return {
      externalId: externalId ?? sourceIdentifier,
      action: "create",
      data: {
        localId: commandResult.result.entityId,
        personId: commandResult.result.personId,
        rowNumber: params.rowNumber,
        sourceIdentifier
      }
    };
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : "Import row failed";
    return {
      externalId: externalId ?? sourceIdentifier,
      action: "failed",
      data: {
        rowNumber: params.rowNumber,
        sourceIdentifier,
        errorMessage
      }
    };
  }
}
const syncExcelCustomersAdapter = {
  providerKey: "excel",
  runMode: "provider",
  operationalTelemetry: true,
  direction: "import",
  supportedEntities: ["customers.person"],
  async getMapping(input) {
    const container = await createRequestContainer();
    const em = container.resolve("em");
    return loadStoredMapping(em, input.entityType, input.scope);
  },
  async *streamImport(input) {
    if (input.entityType !== "customers.person") {
      throw new Error(`Unsupported sync_excel entity type: ${input.entityType}`);
    }
    const container = await createRequestContainer();
    const em = container.resolve("em");
    const commandBus = container.resolve("commandBus");
    const externalIdMappingService = container.resolve("externalIdMappingService");
    const cursor = parseCursor(input.cursor);
    const upload = await resolveUpload(em, input.runId, cursor, input.scope);
    if (!upload) {
      throw new Error("CSV upload session was not found for this sync run.");
    }
    if (input.runId) {
      upload.syncRunId = input.runId;
    }
    upload.status = "importing";
    await em.flush();
    try {
      const attachment = await findOneWithDecryption(
        em,
        Attachment,
        {
          id: upload.attachmentId,
          organizationId: input.scope.organizationId,
          tenantId: input.scope.tenantId
        },
        void 0,
        input.scope
      );
      if (!attachment) {
        throw new Error("CSV upload attachment could not be found.");
      }
      const fileBuffer = await readSyncExcelUploadBuffer(attachment);
      const document = parseCsvDocument(fileBuffer);
      const startOffset = cursor?.uploadId === upload.id ? cursor.offset : 0;
      const commandContext = buildCommandContext(container, input.scope);
      const customFieldDefinitions = await loadImportCustomFieldDefinitions(em, input.scope);
      const emailDedupeIndex = await buildEmailDedupeIndex({
        em,
        rows: document.rows.slice(startOffset),
        mapping: input.mapping,
        scope: input.scope
      });
      for (let offset = startOffset, batchIndex = 0; offset < document.rows.length; offset += input.batchSize, batchIndex += 1) {
        const batchRows = document.rows.slice(offset, offset + input.batchSize);
        const items = [];
        for (let index = 0; index < batchRows.length; index += 1) {
          items.push(await processRow({
            row: batchRows[index],
            rowNumber: offset + index + 1,
            mapping: input.mapping,
            scope: input.scope,
            commandBus,
            commandContext,
            externalIdMappingService,
            emailDedupeIndex,
            customFieldDefinitions,
            em
          }));
        }
        const nextOffset = offset + batchRows.length;
        yield {
          items,
          cursor: createCursor(upload.id, nextOffset),
          hasMore: nextOffset < document.rows.length,
          totalEstimate: document.totalRows,
          processedCount: batchRows.length,
          refreshCoverageEntityTypes: CUSTOMER_IMPORT_COVERAGE_ENTITY_TYPES,
          batchIndex,
          message: `Processed ${nextOffset} of ${document.totalRows} CSV rows`
        };
      }
      upload.status = "completed";
      await em.flush();
    } catch (error) {
      upload.status = "failed";
      await em.flush();
      throw error;
    }
  }
};
export {
  buildPersonPayload,
  createCursor,
  parseCursor,
  syncExcelCustomersAdapter
};
//# sourceMappingURL=customers.js.map
