import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
const DEFAULT_MISMATCH_THRESHOLD = 0.05;
function readUuid(value) {
  return typeof value === "string" && value.trim() ? value.trim() : void 0;
}
function parsePositiveQuantity(value) {
  const parsed = typeof value === "number" ? value : typeof value === "string" ? parseFloat(value) : NaN;
  return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
}
async function validatePrices(em, actions, scope, deps) {
  if (!deps?.catalogProductPriceClass || !deps?.catalogPricingService) return [];
  const threshold = parseFloat(process.env.INBOX_OPS_PRICE_MISMATCH_THRESHOLD || String(DEFAULT_MISMATCH_THRESHOLD));
  const discrepancies = [];
  const now = /* @__PURE__ */ new Date();
  for (const action of actions) {
    if (action.actionType !== "create_order" && action.actionType !== "create_quote") {
      continue;
    }
    const lineItems = action.payload.lineItems || [];
    const orderCurrency = typeof action.payload.currencyCode === "string" ? action.payload.currencyCode.trim().toUpperCase() : null;
    const channelId = readUuid(action.payload.channelId) ?? scope.channelId ?? null;
    const customerId = readUuid(action.payload.customerEntityId) ?? scope.customerId ?? null;
    for (const line of lineItems) {
      if (!line.productId || !line.unitPrice) continue;
      try {
        const pricingContext = {
          channelId,
          customerId,
          customerGroupId: null,
          quantity: parsePositiveQuantity(line.quantity),
          date: now
        };
        const catalogResult = await lookupCatalogPrice(
          em,
          line.productId,
          scope,
          deps.catalogProductPriceClass,
          deps.catalogPricingService,
          pricingContext,
          orderCurrency
        );
        if (catalogResult === null) continue;
        if (orderCurrency && catalogResult.currencyCode && orderCurrency !== catalogResult.currencyCode.toUpperCase()) {
          discrepancies.push({
            type: "currency_mismatch",
            severity: "warning",
            description: `Currency mismatch for "${line.productName}": order uses ${orderCurrency} but catalog price is in ${catalogResult.currencyCode.toUpperCase()}`,
            expectedValue: catalogResult.currencyCode.toUpperCase(),
            foundValue: orderCurrency,
            actionIndex: action.index
          });
          continue;
        }
        const extractedPrice = parseFloat(line.unitPrice);
        const catPrice = parseFloat(catalogResult.price);
        if (isNaN(extractedPrice) || isNaN(catPrice) || catPrice === 0) continue;
        const priceDiff = Math.abs(extractedPrice - catPrice) / catPrice;
        if (priceDiff > threshold) {
          const percentDiff = (priceDiff * 100).toFixed(1);
          discrepancies.push({
            type: "price_mismatch",
            severity: priceDiff > 0.2 ? "error" : "warning",
            description: `Price for "${line.productName}": email says ${line.unitPrice} but catalog price is ${catalogResult.price} (${percentDiff}% difference)`,
            expectedValue: catalogResult.price,
            foundValue: line.unitPrice,
            actionIndex: action.index
          });
        }
      } catch {
      }
    }
  }
  return discrepancies;
}
async function lookupCatalogPrice(em, productId, scope, entityClass, pricingService, pricingContext, orderCurrency) {
  try {
    const rows = await findWithDecryption(
      em,
      entityClass,
      {
        product: productId,
        deletedAt: null,
        organizationId: scope.organizationId,
        tenantId: scope.tenantId
      },
      { populate: ["priceKind", "offer"] },
      { tenantId: scope.tenantId, organizationId: scope.organizationId }
    );
    if (!rows || rows.length === 0) return null;
    const sameCurrencyRows = orderCurrency ? rows.filter((row) => (row.currencyCode ?? "").toUpperCase() === orderCurrency) : rows;
    const candidateRows = sameCurrencyRows.length > 0 ? sameCurrencyRows : rows;
    const priceRecord = await pricingService.resolvePrice(candidateRows, pricingContext);
    if (!priceRecord) return null;
    const priceValue = priceRecord.unitPriceNet ?? priceRecord.unitPriceGross ?? null;
    if (!priceValue) return null;
    return {
      price: priceValue,
      currencyCode: priceRecord.currencyCode ?? null
    };
  } catch {
    return null;
  }
}
export {
  validatePrices
};
//# sourceMappingURL=priceValidator.js.map
