var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/model/strategy/adapter/walletPass/utils.ts
var utils_exports = {};
__export(utils_exports, {
  getApplicableProductIds: () => getApplicableProductIds,
  getBundleItemIsDiscountPrice: () => getBundleItemIsDiscountPrice,
  getBundleItemIsMarkupOrDiscountPrice: () => getBundleItemIsMarkupOrDiscountPrice,
  getBundleItemIsMarkupPrice: () => getBundleItemIsMarkupPrice,
  getBundleItemIsOriginalPrice: () => getBundleItemIsOriginalPrice,
  getBundleItemPrice: () => getBundleItemPrice,
  getMainProductPrice: () => getMainProductPrice,
  getProductQuantity: () => getProductQuantity,
  processVouchers: () => processVouchers,
  recalculateVouchers: () => recalculateVouchers,
  resolveWalletPassLineKey: () => resolveWalletPassLineKey
});
module.exports = __toCommonJS(utils_exports);
var import_decimal = __toESM(require("decimal.js"));
var getProductQuantity = (product) => {
  return product.quantity || product.product_quantity || 1;
};
function resolveWalletPassLineKey(product, indexInOrder) {
  const m = (product == null ? void 0 : product.metadata) || {};
  const u1 = m.product_unique;
  if (u1 != null && String(u1).length > 0)
    return String(u1);
  const u2 = m.unique_identification_number;
  if (u2 != null && String(u2).length > 0)
    return String(u2);
  if ((product == null ? void 0 : product.id) != null && String(product.id).length > 0)
    return `order_item:${product.id}`;
  if ((product == null ? void 0 : product.product_unique_string) != null && String(product.product_unique_string).length > 0) {
    return String(product.product_unique_string);
  }
  return `order_line_${indexInOrder}`;
}
function getExpandedOrderLineQuantity(p) {
  if ((p == null ? void 0 : p._orderLineQuantity) != null && p._orderLineQuantity > 0)
    return p._orderLineQuantity;
  return getProductQuantity(p);
}
function getMaxPassSlotsForExpandedLine(maxPassesPerItem, p) {
  if (maxPassesPerItem <= 0)
    return Infinity;
  return maxPassesPerItem * getExpandedOrderLineQuantity(p);
}
function computePassSlotsIncrement(deductAmount, deductQty, maxPassesPerItem, orderLineQuantity, currentUsage) {
  if (maxPassesPerItem <= 0 || !deductAmount.greaterThan(0))
    return 0;
  const cap = maxPassesPerItem * orderLineQuantity;
  const room = Math.max(0, cap - currentUsage);
  if (room <= 0)
    return 0;
  const raw = Math.max(1, Math.ceil(Number(deductQty)) || 1);
  return Math.min(raw, room);
}
function applyMaxPassUsageIncrements(usageMap, walletPassProductId, maxPassesPerItem, deductionDetails) {
  deductionDetails.forEach((detail) => {
    var _a;
    const lineKey = detail.lineKey;
    if (!lineKey || maxPassesPerItem <= 0)
      return;
    const orderLineQty = detail.orderLineQuantity != null && detail.orderLineQuantity > 0 ? detail.orderLineQuantity : 1;
    const cur = ((_a = usageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
    const inc = computePassSlotsIncrement(
      new import_decimal.default(detail.deductAmount),
      detail.deductQuantity,
      maxPassesPerItem,
      orderLineQty,
      cur
    );
    if (inc <= 0)
      return;
    if (!usageMap.has(walletPassProductId))
      usageMap.set(walletPassProductId, /* @__PURE__ */ new Map());
    const inner = usageMap.get(walletPassProductId);
    inner.set(lineKey, cur + inc);
  });
}
var getRecommendedAmount = (voucher) => {
  console.log("voucher312", voucher);
  const { config, recommended_usage_amount, recommended_pure_product_usage_amount } = voucher;
  const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
  return deductTaxAndFee ? recommended_usage_amount : recommended_pure_product_usage_amount ?? recommended_usage_amount;
};
var getApplicableProductIds = (voucher) => {
  const { available_product_type, available_product_ids } = voucher;
  const productType = available_product_type || "product_all";
  if (productType === "product_all") {
    return null;
  }
  if (productType === "product_collection" || productType === "products") {
    return available_product_ids || [];
  }
  return [];
};
var getApplicableProductsAmount = (voucher, productsData) => {
  const applicableProductIds = getApplicableProductIds(voucher);
  const { config } = voucher;
  const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
  const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
  if (applicableProductIds === null) {
    return productsData.filter((p) => p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new import_decimal.default(0));
  }
  if (applicableProductIds.length === 0) {
    return new import_decimal.default(0);
  }
  return productsData.filter((p) => applicableProductIds.includes(p.product_id) && p[amountField].greaterThan(0)).reduce((sum, p) => sum.plus(p[amountField]), new import_decimal.default(0));
};
var getApplicableProducts = (voucher, productsData) => {
  const applicableProductIds = getApplicableProductIds(voucher);
  if (applicableProductIds === null) {
    return productsData;
  }
  if (applicableProductIds.length === 0) {
    return [];
  }
  return productsData.filter((p) => applicableProductIds.includes(p.product_id));
};
function processVouchers(applicableVouchers, orderTotalAmount, products) {
  console.log(products, "products123");
  const productsCopy = expandProductsWithBundleItems(products, true);
  let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
  const getItemPassUsage = (usageMap, walletPassProductId, lineKey) => {
    var _a;
    return ((_a = usageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
  };
  const filterByMaxPassesPerItem = (products2, usageMap, walletPassProductId, maxPassesPerItem) => {
    if (maxPassesPerItem <= 0)
      return products2;
    return products2.filter((p) => {
      const lineKey = p._walletPassLineKey;
      if (!lineKey)
        return true;
      return getItemPassUsage(usageMap, walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
    });
  };
  const calculateAvailableMaxAmount = (voucher, productsData, itemPassUsage) => {
    const { config } = voucher;
    const { maxDeductionAmount = 0, allowCrossProduct = true, applicableProductLimit = 0, deductTaxAndFee = true, maxPassesPerItem = 0 } = config ?? {};
    const recommendedAmount = getRecommendedAmount(voucher);
    const baseAmount = import_decimal.default.min(
      new import_decimal.default(recommendedAmount),
      new import_decimal.default(maxDeductionAmount)
    );
    const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
    const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
    let applicableProducts = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0));
    if (itemPassUsage) {
      applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsage, voucher.product_id, maxPassesPerItem);
    }
    if (applicableProducts.length === 0) {
      return new import_decimal.default(0);
    }
    let finalApplicableAmount = new import_decimal.default(0);
    if (allowCrossProduct) {
      if (applicableProductLimit > 0) {
        const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
        let remainingLimit = applicableProductLimit;
        for (const product of sortedProducts) {
          if (remainingLimit <= 0)
            break;
          const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
          const deductQty = Math.min(currentAvailableQty, remainingLimit);
          const deductAmount = import_decimal.default.min(
            product[unitPriceField].times(deductQty),
            product[amountField]
          );
          finalApplicableAmount = finalApplicableAmount.plus(deductAmount);
          remainingLimit -= deductQty;
        }
      } else {
        finalApplicableAmount = applicableProducts.reduce(
          (sum, p) => sum.plus(p[amountField]),
          new import_decimal.default(0)
        );
      }
    } else {
      const maxProduct = applicableProducts.reduce(
        (max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
      );
      if (maxPassesPerItem > 0) {
        finalApplicableAmount = import_decimal.default.min(
          maxProduct[unitPriceField].times(maxPassesPerItem),
          maxProduct[amountField]
        );
      } else {
        finalApplicableAmount = maxProduct[amountField];
      }
    }
    return import_decimal.default.min(baseAmount, finalApplicableAmount, remainingOrderAmount);
  };
  const isVoucherAvailable = (voucher, productsData, usedVoucherCounts2, itemPassUsage) => {
    const { config, id, product_id } = voucher;
    const recommendedAmount = getRecommendedAmount(voucher);
    if (recommendedAmount <= 0) {
      return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
    }
    if (remainingOrderAmount.lessThanOrEqualTo(0)) {
      return { isAvailable: false, reasonCode: "exceeds_the_maximum_deduction_limit" };
    }
    const applicableAmount = getApplicableProductsAmount(voucher, productsData);
    if (applicableAmount.lessThanOrEqualTo(0)) {
      return { isAvailable: false, reasonCode: "not_meet_the_required_conditions" };
    }
    if (((config == null ? void 0 : config.maxUsagePerOrder) || 0) > 0) {
      const usedCount = usedVoucherCounts2.get(product_id) || 0;
      if (usedCount >= ((config == null ? void 0 : config.maxUsagePerOrder) || 0)) {
        return { isAvailable: false, reasonCode: "usage_limit_reached" };
      }
    }
    const maxPassesPerItem = (config == null ? void 0 : config.maxPassesPerItem) || 0;
    if (maxPassesPerItem > 0 && itemPassUsage) {
      const deductTaxAndFee = (config == null ? void 0 : config.deductTaxAndFee) ?? true;
      const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
      const availableAfterPassLimit = getApplicableProducts(voucher, productsData).filter((p) => p[amountField].greaterThan(0)).filter((p) => {
        const lineKey = p._walletPassLineKey;
        if (!lineKey)
          return true;
        return getItemPassUsage(itemPassUsage, product_id, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
      });
      if (availableAfterPassLimit.length === 0) {
        return { isAvailable: false, reasonCode: "max_passes_per_item_reached" };
      }
    }
    return { isAvailable: true };
  };
  const usedVoucherCountsForAll = /* @__PURE__ */ new Map();
  const allVouchersWithStatus = applicableVouchers.map((voucher) => {
    const _available_max_amount = calculateAvailableMaxAmount(
      voucher,
      productsCopy
    );
    const availabilityResult = isVoucherAvailable(
      voucher,
      productsCopy,
      usedVoucherCountsForAll
    );
    const _unified_available_status = availabilityResult.isAvailable ? 1 : 0;
    return {
      ...voucher,
      _available_max_amount: _available_max_amount.toNumber(),
      // 转换为数字
      _unified_available_status,
      ...availabilityResult.reasonCode && { reasonCode: availabilityResult.reasonCode }
    };
  });
  const recommendedVouchers = [];
  const usedVoucherCounts = /* @__PURE__ */ new Map();
  const productsForRecommendation = expandProductsWithBundleItems(products, true);
  remainingOrderAmount = new import_decimal.default(orderTotalAmount);
  const itemPassUsageMap = /* @__PURE__ */ new Map();
  const applyVoucher = (voucher) => {
    const availabilityCheck = isVoucherAvailable(
      voucher,
      productsForRecommendation,
      usedVoucherCounts,
      itemPassUsageMap
    );
    if (!availabilityCheck.isAvailable) {
      return false;
    }
    const { config, id, product_id } = voucher;
    const { maxDeductionAmount = 0, allowCrossProduct = true, applicableProductLimit = 0, deductTaxAndFee = true, maxPassesPerItem = 0 } = config ?? {};
    const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
    const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
    let applicableProducts = getApplicableProducts(
      voucher,
      productsForRecommendation
    ).filter((p) => p[amountField].greaterThan(0));
    applicableProducts = filterByMaxPassesPerItem(applicableProducts, itemPassUsageMap, product_id, maxPassesPerItem);
    if (applicableProducts.length === 0)
      return false;
    const usageAmount = typeof voucher.edit_current_amount === "number" ? voucher.edit_current_amount : getRecommendedAmount(voucher);
    const baseAmount = import_decimal.default.min(
      new import_decimal.default(usageAmount),
      new import_decimal.default(maxDeductionAmount)
    );
    let calculatedAvailableMaxAmount = new import_decimal.default(0);
    if (allowCrossProduct) {
      if (applicableProductLimit > 0) {
        const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
        let remainingLimit = applicableProductLimit;
        for (const product of sortedProducts) {
          if (remainingLimit <= 0)
            break;
          const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
          const deductQty = Math.min(currentAvailableQty, remainingLimit);
          const deductAmount = import_decimal.default.min(
            product[unitPriceField].times(deductQty),
            product[amountField]
          );
          calculatedAvailableMaxAmount = calculatedAvailableMaxAmount.plus(deductAmount);
          remainingLimit -= deductQty;
        }
      } else {
        calculatedAvailableMaxAmount = applicableProducts.reduce(
          (sum, p) => sum.plus(p[amountField]),
          new import_decimal.default(0)
        );
      }
    } else {
      const maxProduct = applicableProducts.reduce(
        (max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
      );
      if (maxPassesPerItem > 0) {
        calculatedAvailableMaxAmount = import_decimal.default.min(
          maxProduct[unitPriceField].times(maxPassesPerItem),
          maxProduct[amountField]
        );
      } else {
        calculatedAvailableMaxAmount = maxProduct[amountField];
      }
    }
    const availableMaxAmount = import_decimal.default.min(
      baseAmount,
      calculatedAvailableMaxAmount,
      remainingOrderAmount
    );
    const maxDeduction = import_decimal.default.min(
      new import_decimal.default(usageAmount),
      new import_decimal.default(maxDeductionAmount)
    );
    let deductionLeft = maxDeduction;
    const deductionDetails = [];
    if (allowCrossProduct) {
      const sortedProducts = [...applicableProducts].sort(
        (a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1
      );
      let remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
      for (const product of sortedProducts) {
        if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
          break;
        const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
        const availableQty = Math.min(currentAvailableQty, remainingLimit);
        const maxDeductForProduct = import_decimal.default.min(
          product[unitPriceField].times(availableQty),
          product[amountField]
        );
        const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
        const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
        product[amountField] = product[amountField].minus(actualDeductAmount);
        deductionLeft = deductionLeft.minus(actualDeductAmount);
        remainingLimit -= actualDeductQty;
        deductionDetails.push({
          product_id: product.product_id,
          parent_product_id: product.parent_product_id || null,
          is_bundle_item: product.is_bundle_item || false,
          lineKey: product._walletPassLineKey,
          orderLineQuantity: getExpandedOrderLineQuantity(product),
          deductAmount: actualDeductAmount.toNumber(),
          // 转换为数字
          deductQuantity: actualDeductQty
          // 抵扣涉及的数量（用于记录）
        });
      }
    } else {
      const targetProduct = applicableProducts.reduce(
        (max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
      );
      let maxDeductForProduct = targetProduct[amountField];
      if (maxPassesPerItem > 0) {
        maxDeductForProduct = import_decimal.default.min(
          targetProduct[unitPriceField].times(maxPassesPerItem),
          targetProduct[amountField]
        );
      }
      const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
      const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
      targetProduct[amountField] = targetProduct[amountField].minus(actualDeductAmount);
      deductionLeft = deductionLeft.minus(actualDeductAmount);
      deductionDetails.push({
        product_id: targetProduct.product_id,
        parent_product_id: targetProduct.parent_product_id || null,
        is_bundle_item: targetProduct.is_bundle_item || false,
        lineKey: targetProduct._walletPassLineKey,
        orderLineQuantity: getExpandedOrderLineQuantity(targetProduct),
        deductAmount: actualDeductAmount.toNumber(),
        deductQuantity: actualDeductQty
      });
    }
    const totalDeducted = maxDeduction.minus(deductionLeft);
    if (totalDeducted.greaterThan(0)) {
      remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
      usedVoucherCounts.set(product_id, (usedVoucherCounts.get(product_id) || 0) + 1);
      applyMaxPassUsageIncrements(itemPassUsageMap, product_id, maxPassesPerItem, deductionDetails);
      recommendedVouchers.push({
        ...voucher,
        actualDeduction: totalDeducted.toNumber(),
        // 转换为数字
        deductionDetails,
        _available_max_amount: availableMaxAmount.toNumber(),
        // 转换为数字
        _unified_available_status: 1
      });
      return true;
    }
    return false;
  };
  applicableVouchers.forEach((voucher) => {
    applyVoucher(voucher);
  });
  const recommendedMap = /* @__PURE__ */ new Map();
  recommendedVouchers.forEach((v) => {
    recommendedMap.set(v.id, v);
  });
  const allWithEnhancedData = allVouchersWithStatus.map((voucher) => {
    if (recommendedMap.has(voucher.id)) {
      return recommendedMap.get(voucher.id);
    } else {
      return {
        ...voucher,
        actualDeduction: 0,
        deductionDetails: []
        // 保留 reasonCode（如果不可用的话）
      };
    }
  });
  return {
    recommended: recommendedVouchers,
    transformList: allWithEnhancedData
  };
}
function recalculateVouchers(allVouchers, selectedVouchers, orderTotalAmount, products) {
  const productsForCalc = expandProductsWithBundleItems(products, true);
  let remainingOrderAmount = new import_decimal.default(orderTotalAmount);
  const selectedWithDetails = [];
  const itemPassUsageMap = /* @__PURE__ */ new Map();
  const getItemPassUsageRecalc = (walletPassProductId, lineKey) => {
    var _a;
    return ((_a = itemPassUsageMap.get(walletPassProductId)) == null ? void 0 : _a.get(lineKey)) || 0;
  };
  const filterByMaxPassesPerItemRecalc = (products2, walletPassProductId, maxPassesPerItem) => {
    if (maxPassesPerItem <= 0)
      return products2;
    return products2.filter((p) => {
      const lineKey = p._walletPassLineKey;
      if (!lineKey)
        return true;
      return getItemPassUsageRecalc(walletPassProductId, lineKey) < getMaxPassSlotsForExpandedLine(maxPassesPerItem, p);
    });
  };
  selectedVouchers.forEach((selectedVoucher) => {
    const { config, id } = selectedVoucher;
    const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
    const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
    const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
    let applicableProducts = getApplicableProducts(
      selectedVoucher,
      productsForCalc
    ).filter((p) => p[amountField].greaterThan(0));
    applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, selectedVoucher.product_id, maxPassesPerItem);
    if (applicableProducts.length === 0) {
      selectedWithDetails.push({
        ...selectedVoucher,
        actualDeduction: 0,
        deductionDetails: [],
        _available_max_amount: 0,
        _unified_available_status: 0,
        reasonCode: "not_meet_the_required_conditions"
      });
      return;
    }
    const usageAmount = typeof selectedVoucher.edit_current_amount === "number" ? selectedVoucher.edit_current_amount : getRecommendedAmount(selectedVoucher);
    const maxDeduction = import_decimal.default.min(
      new import_decimal.default(usageAmount),
      new import_decimal.default(maxDeductionAmount),
      remainingOrderAmount
    );
    let deductionLeft = maxDeduction;
    const deductionDetails = [];
    if (allowCrossProduct) {
      const sortedProducts = [...applicableProducts].sort(
        (a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1
      );
      let remainingLimit = applicableProductLimit > 0 ? applicableProductLimit : Infinity;
      for (const product of sortedProducts) {
        if (deductionLeft.lessThanOrEqualTo(0) || remainingLimit <= 0)
          break;
        const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
        const availableQty = Math.min(currentAvailableQty, remainingLimit);
        const maxDeductForProduct = import_decimal.default.min(
          product[unitPriceField].times(availableQty),
          product[amountField]
        );
        const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
        const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(product[unitPriceField]).toNumber());
        product[amountField] = product[amountField].minus(actualDeductAmount);
        deductionLeft = deductionLeft.minus(actualDeductAmount);
        remainingLimit -= actualDeductQty;
        deductionDetails.push({
          product_id: product.product_id,
          parent_product_id: product.parent_product_id || null,
          is_bundle_item: product.is_bundle_item || false,
          lineKey: product._walletPassLineKey,
          orderLineQuantity: getExpandedOrderLineQuantity(product),
          deductAmount: actualDeductAmount.toNumber(),
          // 转换为数字
          deductQuantity: actualDeductQty
          // 抵扣涉及的数量（用于记录）
        });
      }
    } else {
      const targetProduct = applicableProducts.reduce(
        (max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
      );
      let maxDeductForProduct = targetProduct[amountField];
      if (maxPassesPerItem > 0) {
        maxDeductForProduct = import_decimal.default.min(
          targetProduct[unitPriceField].times(maxPassesPerItem),
          targetProduct[amountField]
        );
      }
      const actualDeductAmount = import_decimal.default.min(deductionLeft, maxDeductForProduct);
      const actualDeductQty = Math.ceil(actualDeductAmount.dividedBy(targetProduct[unitPriceField]).toNumber());
      targetProduct[amountField] = targetProduct[amountField].minus(actualDeductAmount);
      deductionLeft = deductionLeft.minus(actualDeductAmount);
      deductionDetails.push({
        product_id: targetProduct.product_id,
        parent_product_id: targetProduct.parent_product_id || null,
        is_bundle_item: targetProduct.is_bundle_item || false,
        lineKey: targetProduct._walletPassLineKey,
        orderLineQuantity: getExpandedOrderLineQuantity(targetProduct),
        deductAmount: actualDeductAmount.toNumber(),
        deductQuantity: actualDeductQty
      });
    }
    const totalDeducted = maxDeduction.minus(deductionLeft);
    remainingOrderAmount = remainingOrderAmount.minus(totalDeducted);
    applyMaxPassUsageIncrements(itemPassUsageMap, selectedVoucher.product_id, maxPassesPerItem, deductionDetails);
    selectedWithDetails.push({
      ...selectedVoucher,
      actualDeduction: totalDeducted.toNumber(),
      // 转换为数字
      deductionDetails,
      _available_max_amount: totalDeducted.toNumber(),
      // 转换为数字
      _unified_available_status: totalDeducted.greaterThan(0) ? 1 : 0
    });
  });
  const selectedIds = new Set(selectedVouchers.map((v) => v.id));
  const usedVoucherCounts = /* @__PURE__ */ new Map();
  selectedVouchers.forEach((v) => {
    usedVoucherCounts.set(v.product_id, (usedVoucherCounts.get(v.product_id) || 0) + 1);
  });
  const allWithUpdatedStatus = allVouchers.map((voucher) => {
    if (selectedIds.has(voucher.id)) {
      const selectedDetail = selectedWithDetails.find(
        (v) => v.id === voucher.id
      );
      return selectedDetail || voucher;
    }
    const { config, id, product_id } = voucher;
    const { maxDeductionAmount, allowCrossProduct, applicableProductLimit, deductTaxAndFee = true, maxPassesPerItem = 0 } = config;
    const unitPriceField = deductTaxAndFee ? "unitPriceWithTax" : "unitPricePure";
    const amountField = deductTaxAndFee ? "remainingAmountWithTax" : "remainingAmountPure";
    const recommendedAmount = getRecommendedAmount(voucher);
    let isAvailable = true;
    let calculatedMaxAmount = new import_decimal.default(0);
    let reasonCode;
    if (recommendedAmount <= 0) {
      isAvailable = false;
      reasonCode = "not_meet_the_required_conditions";
    } else if (remainingOrderAmount.lessThanOrEqualTo(0)) {
      isAvailable = false;
      reasonCode = "exceeds_the_maximum_deduction_limit";
    } else {
      if (config.maxUsagePerOrder > 0) {
        const usedCount = usedVoucherCounts.get(product_id) || 0;
        if (usedCount >= config.maxUsagePerOrder) {
          isAvailable = false;
          reasonCode = "usage_limit_reached";
        }
      }
      if (isAvailable) {
        let applicableProducts = getApplicableProducts(
          voucher,
          productsForCalc
        ).filter((p) => p[amountField].greaterThan(0));
        applicableProducts = filterByMaxPassesPerItemRecalc(applicableProducts, product_id, maxPassesPerItem);
        if (applicableProducts.length === 0) {
          isAvailable = false;
          reasonCode = "not_meet_the_required_conditions";
        } else {
          const baseAmount = import_decimal.default.min(
            new import_decimal.default(recommendedAmount),
            new import_decimal.default(maxDeductionAmount)
          );
          if (allowCrossProduct) {
            if (applicableProductLimit > 0) {
              const sortedProducts = [...applicableProducts].sort((a, b) => a[amountField].comparedTo(b[amountField]) > 0 ? -1 : 1);
              let remainingLimit = applicableProductLimit;
              for (const product of sortedProducts) {
                if (remainingLimit <= 0)
                  break;
                const currentAvailableQty = Math.ceil(product[amountField].dividedBy(product[unitPriceField]).toNumber());
                const deductQty = Math.min(currentAvailableQty, remainingLimit);
                const deductAmount = import_decimal.default.min(
                  product[unitPriceField].times(deductQty),
                  product[amountField]
                );
                calculatedMaxAmount = calculatedMaxAmount.plus(deductAmount);
                remainingLimit -= deductQty;
              }
            } else {
              calculatedMaxAmount = applicableProducts.reduce(
                (sum, p) => sum.plus(p[amountField]),
                new import_decimal.default(0)
              );
            }
          } else {
            const maxProduct = applicableProducts.reduce(
              (max, p) => p[unitPriceField].greaterThan(max[unitPriceField]) ? p : max
            );
            if (maxPassesPerItem > 0) {
              calculatedMaxAmount = import_decimal.default.min(
                maxProduct[unitPriceField].times(maxPassesPerItem),
                maxProduct[amountField]
              );
            } else {
              calculatedMaxAmount = maxProduct[amountField];
            }
          }
          calculatedMaxAmount = import_decimal.default.min(
            baseAmount,
            calculatedMaxAmount,
            remainingOrderAmount
          );
          if (calculatedMaxAmount.lessThanOrEqualTo(0)) {
            isAvailable = false;
            reasonCode = "exceeds_the_maximum_deduction_limit";
          }
        }
      }
    }
    return {
      ...voucher,
      _available_max_amount: calculatedMaxAmount.toNumber(),
      // 转换为数字
      _unified_available_status: isAvailable ? 1 : 0,
      ...reasonCode && { reasonCode }
    };
  });
  return {
    allWithUpdatedStatus,
    selectedWithDetails
  };
}
var getMainProductPrice = (product, isDeductTaxAndFee) => {
  var _a, _b, _c, _d, _e;
  let mainProductPrice = new import_decimal.default((product == null ? void 0 : product.main_product_selling_price) || ((_a = product.metadata) == null ? void 0 : _a.main_product_selling_price) || 0);
  for (let bundleItem of (product == null ? void 0 : product.product_bundle) || []) {
    if (getBundleItemIsMarkupOrDiscountPrice(bundleItem)) {
      const bundleItemPrice = new import_decimal.default(bundleItem.bundle_selling_price ?? 0);
      mainProductPrice = mainProductPrice.add(bundleItemPrice.times(bundleItem.num));
    }
  }
  let taxFee = new import_decimal.default((product == null ? void 0 : product.tax_fee) || ((_b = product == null ? void 0 : product.metadata) == null ? void 0 : _b.main_product_attached_bundle_tax_fee) || 0).add(((_c = product == null ? void 0 : product.metadata) == null ? void 0 : _c.tax_fee_rounding_remainder) || 0);
  if (product.is_price_include_tax === 1) {
    taxFee = new import_decimal.default(0);
  }
  const surchargeFee = new import_decimal.default(((_d = product == null ? void 0 : product.metadata) == null ? void 0 : _d.main_product_attached_bundle_surcharge_fee) || 0).add(((_e = product == null ? void 0 : product.metadata) == null ? void 0 : _e.surcharge_rounding_remainder) || 0);
  const taxAndFeeTotal = taxFee.add(surchargeFee);
  if (isDeductTaxAndFee) {
    mainProductPrice = mainProductPrice.add(taxAndFeeTotal);
  }
  return mainProductPrice.toNumber();
};
var getBundleItemPrice = (bundleItem, parentQuantity, isDeductTaxAndFee) => {
  var _a;
  const totalQuantity = bundleItem.num * parentQuantity;
  let bundleItemPrice = new import_decimal.default(bundleItem.bundle_selling_price ?? 0).times(totalQuantity);
  if (isDeductTaxAndFee) {
    let taxFee = new import_decimal.default(bundleItem.tax_fee ?? 0).times(totalQuantity);
    if (bundleItem.is_price_include_tax === 1) {
      taxFee = new import_decimal.default(0);
    }
    const surchargeFee = new import_decimal.default(((_a = bundleItem.metadata) == null ? void 0 : _a.surcharge_fee) ?? 0).times(totalQuantity);
    bundleItemPrice = bundleItemPrice.add(taxFee).add(surchargeFee);
  }
  return bundleItemPrice.toNumber();
};
var expandProductsWithBundleItems = (products, deductTaxAndFee) => {
  const expandedProducts = [];
  products.forEach((product, indexInOrder) => {
    const productQuantity = getProductQuantity(product);
    const parentLineKey = resolveWalletPassLineKey(product, indexInOrder);
    const unitPriceWithTax = getMainProductPrice(product, true);
    const unitPricePure = getMainProductPrice(product, false);
    expandedProducts.push({
      ...product,
      is_bundle_item: false,
      parent_product_id: null,
      _walletPassLineKey: parentLineKey,
      _orderLineQuantity: productQuantity,
      // 单价（用于按 quantity 计算抵扣）
      unitPriceWithTax: new import_decimal.default(unitPriceWithTax),
      unitPricePure: new import_decimal.default(unitPricePure),
      // 剩余可抵扣数量
      remainingQuantity: productQuantity,
      // 含税费的剩余金额
      remainingAmountWithTax: new import_decimal.default(unitPriceWithTax).times(productQuantity),
      // 纯商品金额（不含税费）
      remainingAmountPure: new import_decimal.default(unitPricePure).times(productQuantity)
    });
    if (product.product_bundle && product.product_bundle.length > 0) {
      product.product_bundle.forEach((bundleItem) => {
        if (getBundleItemIsOriginalPrice(bundleItem)) {
          const bundleQuantity = bundleItem.num * productQuantity;
          const bundleLineKey = `${parentLineKey}#bundle:${bundleItem.bundle_id}:${bundleItem.bundle_product_id}`;
          const bundleUnitPriceWithTax = new import_decimal.default(getBundleItemPrice(bundleItem, 1, true)).dividedBy(bundleItem.num);
          const bundleUnitPricePure = new import_decimal.default(getBundleItemPrice(bundleItem, 1, false)).dividedBy(bundleItem.num);
          expandedProducts.push({
            ...bundleItem,
            product_id: bundleItem.bundle_product_id,
            // 使用 bundle_product_id 作为 product_id
            is_bundle_item: true,
            parent_product_id: product.product_id,
            quantity: bundleQuantity,
            // 子商品数量 * 主商品数量
            _walletPassLineKey: bundleLineKey,
            _orderLineQuantity: bundleQuantity,
            // 单价（用于按 quantity 计算抵扣）
            unitPriceWithTax: bundleUnitPriceWithTax,
            unitPricePure: bundleUnitPricePure,
            // 剩余可抵扣数量
            remainingQuantity: bundleQuantity,
            // 含税费的剩余金额
            remainingAmountWithTax: new import_decimal.default(getBundleItemPrice(bundleItem, productQuantity, true)),
            // 纯商品金额（不含税费）
            remainingAmountPure: new import_decimal.default(getBundleItemPrice(bundleItem, productQuantity, false))
          });
        }
      });
    }
  });
  return expandedProducts;
};
var getBundleItemIsOriginalPrice = (item) => {
  return (item == null ? void 0 : item.price_type) === "markup" && (item == null ? void 0 : item.price_type_ext) === "product_price";
};
var getBundleItemIsMarkupPrice = (item) => {
  return (item == null ? void 0 : item.price_type) === "markup" && ((item == null ? void 0 : item.price_type_ext) === "" || !(item == null ? void 0 : item.price_type_ext));
};
var getBundleItemIsDiscountPrice = (item) => {
  return (item == null ? void 0 : item.price_type) === "markdown" && ((item == null ? void 0 : item.price_type_ext) === "" || !(item == null ? void 0 : item.price_type_ext));
};
var getBundleItemIsMarkupOrDiscountPrice = (item) => {
  return getBundleItemIsMarkupPrice(item) || getBundleItemIsDiscountPrice(item);
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  getApplicableProductIds,
  getBundleItemIsDiscountPrice,
  getBundleItemIsMarkupOrDiscountPrice,
  getBundleItemIsMarkupPrice,
  getBundleItemIsOriginalPrice,
  getBundleItemPrice,
  getMainProductPrice,
  getProductQuantity,
  processVouchers,
  recalculateVouchers,
  resolveWalletPassLineKey
});
