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/server/utils/small-ticket.ts
var small_ticket_exports = {};
__export(small_ticket_exports, {
  buildSmallTicketData: () => buildSmallTicketData,
  hasSmallTicketData: () => hasSmallTicketData
});
module.exports = __toCommonJS(small_ticket_exports);
var import_dayjs = __toESM(require("dayjs"));
var import_decimal = __toESM(require("decimal.js"));
var DEFAULT_LOCALES = ["en", "zh_CN"];
var LABELS = {
  en: {
    contactName: "Contact name",
    contactMobile: "Contact Mobile",
    email: "email",
    dineIn: "Dine-in",
    takeAway: "Take away",
    delivery: "Delivery",
    pickUp: "Pick-up",
    shopService: "Dine-in",
    pickUpTime: "Pick-up time",
    asap: "ASAP",
    cash: "Cash",
    eftpos: "Eftpos",
    wallet: "Wallet",
    giftCard: "Gift card",
    remainingAmount: "Remaining amount",
    redeemPoints: "Redeem points",
    remainingPoints: "Remaining points",
    table: "Table",
    orderDiscount: "Order discount",
    payProcessingFee: "Pay processing fee",
    rounding: "Rounding"
  },
  zh_CN: {
    contactName: "联系人姓名",
    contactMobile: "联系电话",
    email: "邮箱",
    dineIn: "堂食",
    takeAway: "外带",
    delivery: "配送",
    pickUp: "自提",
    shopService: "堂食",
    pickUpTime: "取餐时间",
    asap: "尽快",
    cash: "现金支付",
    eftpos: "刷卡支付",
    wallet: "钱包支付",
    giftCard: "礼品卡",
    remainingAmount: "剩余金额",
    redeemPoints: "本次使用积分",
    remainingPoints: "剩余积分",
    table: "桌台",
    orderDiscount: "整单折扣",
    payProcessingFee: "支付手续费",
    rounding: "抹零"
  },
  zh_HK: {
    contactName: "聯絡人姓名",
    contactMobile: "聯絡電話",
    email: "電郵",
    dineIn: "堂食",
    takeAway: "外帶",
    delivery: "配送",
    pickUp: "自取",
    shopService: "堂食",
    pickUpTime: "取餐時間",
    asap: "盡快",
    cash: "現金支付",
    eftpos: "刷卡支付",
    wallet: "錢包支付",
    giftCard: "禮品卡",
    remainingAmount: "剩餘金額",
    redeemPoints: "本次使用積分",
    remainingPoints: "剩餘積分",
    table: "桌台",
    orderDiscount: "整單折扣",
    payProcessingFee: "支付手續費",
    rounding: "抹零"
  }
};
function buildSmallTicketData(params) {
  const order = params.order || {};
  const shopInfo = params.shopInfo || {};
  const locales = resolveLocales(shopInfo, params.locales);
  const productMap = params.productMap || {};
  return locales.reduce((data, locale) => {
    data[locale] = buildLocaleData({ order, shopInfo, locale, productMap });
    return data;
  }, {});
}
function hasSmallTicketData(value) {
  return !!value && typeof value === "object" && Object.keys(value).length > 0;
}
function buildLocaleData(params) {
  const { order, shopInfo, locale, productMap } = params;
  const products = buildProducts(order, locale, productMap);
  const summary = getSummary(order);
  const currencySymbol = getCurrencySymbol(order, shopInfo);
  return {
    base_data: buildBaseData({ order, shopInfo, locale }),
    products,
    fees: buildFees({ order, shopInfo, locale, products, summary, currencySymbol }),
    customer: buildCustomer(order, locale),
    appointment: buildAppointment(order, locale),
    // delivery: buildDelivery(order, locale),
    resources: buildResources(order, locale),
    payment_data: buildPaymentData({ order, locale, currencySymbol }),
    tickets: Array.isArray(order.tickets) ? order.tickets : [],
    source_shop: [],
    refund_data: [],
    expend_data: []
  };
}
function buildBaseData(params) {
  var _a;
  const { order, shopInfo, locale } = params;
  const orderNumber = stringify(
    order.order_number || order.shop_full_order_number || order.shop_order_number || order.external_sale_number
  );
  return {
    shop_name: stringify(shopInfo.name || order.shop_name),
    note: stringify(order.note),
    shop_order_number: stringify(order.shop_order_number),
    order_number: orderNumber,
    shop_tax_number: stringify(shopInfo.tax_number || order.shop_tax_number),
    shop_phone: stringify(shopInfo.phone || order.shop_phone),
    shop_address: stringify(shopInfo.address || buildShopAddress(shopInfo) || order.shop_address),
    original_payment_status: stringify(order.payment_status),
    is_repeat: 0,
    buzzer: stringify(order.buzzer || order.pickup_number || ((_a = order.metadata) == null ? void 0 : _a.buzzer)),
    order_no: orderNumber,
    order_time: formatDateTime(order.created_at || order.sales_time || /* @__PURE__ */ new Date(), locale)
  };
}
function buildProducts(order, locale, productMap) {
  const products = Array.isArray(order.products) ? order.products : [];
  return products.map((product) => {
    const quantity = toNumber(product.product_quantity ?? product.quantity ?? product.num ?? 1, 1);
    const originalPrice = product.original_price ?? product.selling_price ?? product.payment_price ?? product.price ?? 0;
    const sellingPrice = product.selling_price ?? product.payment_price ?? product.price ?? originalPrice;
    const productTitle = resolveProductTitle({ product, productMap, locale });
    return {
      product_title: productTitle,
      product_quantity: quantity,
      selling_price: formatMoney(sellingPrice, getCurrencySymbol(order, null)),
      original_price: formatMoney(originalPrice, getCurrencySymbol(order, null)),
      total_original_price: formatMoney(new import_decimal.default(toMoneyNumber(originalPrice)).mul(quantity), getCurrencySymbol(order, null)),
      extension_list: Array.isArray(product.extension_list) ? product.extension_list : [],
      ...Array.isArray(product.options) ? {
        options: product.options.map((option) => ({
          name: getLocalizedValue(option.name || option.title, locale),
          value: getLocalizedValue(option.value || option.option || option.item, locale)
        }))
      } : {},
      ...product.variant ? { variant: getLocalizedValue(product.variant, locale) } : {},
      ...Array.isArray(product.combinations) ? { combinations: product.combinations } : {}
    };
  });
}
function resolveProductTitle(params) {
  var _a, _b;
  const { product, productMap, locale } = params;
  const ownTitle = getLocalizedValue(
    product.product_title || product.title || product.name || ((_a = product.product) == null ? void 0 : _a.title),
    locale
  );
  if (ownTitle)
    return ownTitle;
  const productId = product.product_id ?? product.id;
  const fallbackProduct = productId !== void 0 && productId !== null ? productMap[productId] || productMap[String(productId)] : null;
  if (!fallbackProduct)
    return "";
  return getLocalizedValue(
    fallbackProduct.product_title || fallbackProduct.title || fallbackProduct.name || fallbackProduct.format_title || ((_b = fallbackProduct.product) == null ? void 0 : _b.title),
    locale
  );
}
function buildFees(params) {
  const { order, shopInfo, locale, products, summary, currencySymbol } = params;
  const fees = [];
  for (const surcharge of normalizeArray(order.surcharges || summary.surcharges)) {
    const value = surcharge.amount ?? surcharge.value ?? surcharge.total_amount;
    if (!isNonZero(value))
      continue;
    fees.push({
      item: getLocalizedValue(surcharge.name || surcharge.title || surcharge.item, locale),
      value: formatMoney(value, currencySymbol)
    });
  }
  const discountAmount = summary.discount_amount || order.discount_amount || order.shop_discount;
  if (isNonZero(discountAmount)) {
    fees.push({
      item: label(locale, "orderDiscount"),
      value: formatMoney(new import_decimal.default(toMoneyNumber(discountAmount)).neg(), currencySymbol)
    });
  }
  const taxFee = summary.tax_fee || order.tax_fee;
  if (isNonZero(taxFee)) {
    fees.push({
      item: stringify(summary.tax_title || order.tax_title || shopInfo.tax_title),
      value: formatMoney(taxFee, currencySymbol)
    });
  }
  const roundingAmount = summary.rounding_amount || order.rounding_amount;
  if (isNonZero(roundingAmount)) {
    fees.push({
      item: label(locale, "rounding"),
      value: formatMoney(roundingAmount, currencySymbol)
    });
  }
  const payProcessingFee = summary.pay_service_charge_amount || order.pay_service_charge_amount;
  if (isNonZero(payProcessingFee)) {
    fees.push({
      item: label(locale, "payProcessingFee"),
      value: formatMoney(payProcessingFee, currencySymbol)
    });
  }
  return {
    fees,
    countFee: {
      total_amount: formatMoney(summary.total_amount || order.total_amount, currencySymbol),
      product_expect_amount: formatMoney(
        summary.product_expect_amount || summary.product_amount || order.product_expect_amount,
        currencySymbol
      ),
      expect_amount: formatMoney(summary.expect_amount || order.expect_amount || summary.total_amount || order.total_amount, currencySymbol),
      product_quantity: toNumber(
        summary.product_quantity || products.reduce((sum, product) => sum + product.product_quantity, 0),
        0
      ),
      has_pay: formatMoney(sumPayments(order.payments), currencySymbol),
      payment_method: "",
      tax_title: stringify(summary.tax_title || order.tax_title || shopInfo.tax_title),
      total_refund_amount: formatMoney(summary.total_refund_amount || order.total_refund_amount, currencySymbol),
      ...isNonZero(roundingAmount) ? { rounding_amount: formatMoney(roundingAmount, currencySymbol) } : {},
      ...isNonZero(discountAmount) ? { order_total_discount: formatMoney(discountAmount, currencySymbol) } : {},
      ...isNonZero(payProcessingFee) ? { pay_processing_fee: formatMoney(payProcessingFee, currencySymbol) } : {},
      ...isNonZero(taxFee) ? { tax_fee: formatMoney(taxFee, currencySymbol) } : {}
    }
  };
}
function buildCustomer(order, locale) {
  var _a, _b, _c, _d;
  return [
    { item: label(locale, "contactName"), value: normalizeCustomerDisplayValue(order.customer_name || ((_a = order.customer) == null ? void 0 : _a.name) || ((_b = order.customer) == null ? void 0 : _b.display_name)) },
    { item: label(locale, "contactMobile"), value: stringify(order.phone || ((_c = order.customer) == null ? void 0 : _c.phone)) },
    { item: label(locale, "email"), value: stringify(order.email || ((_d = order.customer) == null ? void 0 : _d.email)) }
  ];
}
function normalizeCustomerDisplayValue(value) {
  const text = stringify(value).trim();
  if (!text)
    return "Walk-In";
  if (text.toLowerCase() === "select a customer")
    return "Walk-In";
  return text;
}
function buildAppointment(order, locale) {
  var _a, _b, _c, _d;
  const tableName = order.table_name || ((_a = order.metadata) == null ? void 0 : _a.table_name) || ((_c = (_b = order.metadata) == null ? void 0 : _b.table) == null ? void 0 : _c.name) || ((_d = order.form_data) == null ? void 0 : _d.table_name);
  if (!tableName)
    return [];
  return [
    {
      item: label(locale, "table"),
      value: getLocalizedValue(tableName, locale)
    }
  ];
}
function buildResources(order, locale) {
  return normalizeArray(order.resources || order.resource_list).map((resource) => ({
    id: resource.id || resource.resource_id || "",
    code: "",
    title: getLocalizedValue(resource.title || resource.name, locale),
    form_title: getLocalizedValue(resource.form_title || resource.type || "", locale)
  }));
}
function buildPaymentData(params) {
  const payments = normalizeArray(params.order.payments);
  return payments.filter((payment) => isPrintablePayment(payment)).map((payment) => {
    var _a;
    const items = [
      {
        item: paymentMethodName(payment, params.locale),
        value: formatMoney(payment.amount ?? payment.origin_amount, params.currencySymbol)
      }
    ];
    const fundRecord = getFundRecord(payment);
    if (fundRecord) {
      items.push(...buildFundRecordPaymentItems({ payment, fundRecord, locale: params.locale, currencySymbol: params.currencySymbol }));
    } else {
      const remainingAmount = payment.remaining_amount ?? payment.balance ?? ((_a = payment.metadata) == null ? void 0 : _a.remaining_amount);
      if (remainingAmount !== void 0 && remainingAmount !== null) {
        items.push({
          item: label(params.locale, "remainingAmount"),
          value: formatMoney(remainingAmount, params.currencySymbol)
        });
      }
    }
    items.push({
      item: formatDateTime(payment.paid_at || payment.created_at || payment.updated_at || /* @__PURE__ */ new Date(), params.locale),
      value: ""
    });
    return items;
  });
}
function buildFundRecordPaymentItems(params) {
  const { payment, fundRecord, locale, currencySymbol } = params;
  const items = [];
  const usingBeforeValue = fundRecord.using_before_value;
  const usingAfterValue = fundRecord.using_after_value;
  if (isPointCardPayment(payment) && usingBeforeValue !== void 0 && usingAfterValue !== void 0) {
    const usedPoints = new import_decimal.default(toMoneyNumber(usingBeforeValue)).minus(toMoneyNumber(usingAfterValue));
    items.push({
      item: label(locale, "redeemPoints"),
      value: trimDecimal(usedPoints)
    });
    items.push({
      item: label(locale, "remainingPoints"),
      value: trimDecimal(new import_decimal.default(toMoneyNumber(usingAfterValue)))
    });
    return items;
  }
  if (usingAfterValue !== void 0 && usingAfterValue !== null) {
    items.push({
      item: label(locale, "remainingAmount"),
      value: formatMoney(usingAfterValue, currencySymbol)
    });
  }
  return items;
}
function getFundRecord(payment) {
  const fundRecord = payment.fund_record;
  if (!fundRecord || typeof fundRecord !== "object" || Array.isArray(fundRecord))
    return null;
  if (!fundRecord.voucher_id && !fundRecord.code)
    return null;
  return fundRecord;
}
function isPointCardPayment(payment) {
  var _a;
  const code = stringify(payment.code || payment.payment_method).toUpperCase();
  const type = stringify(payment.type || ((_a = payment.fund_record) == null ? void 0 : _a.tag)).toLowerCase();
  return code === "POINTCARD" || type === "point_card";
}
function maskMachineCode(code) {
  const text = stringify(code);
  if (text.length <= 6)
    return text;
  return `${text.slice(0, 2)}**${text.slice(-4)}`;
}
function trimDecimal(value) {
  return value.toDecimalPlaces(2).toFixed(2).replace(/\.?0+$/, "");
}
function getFundRecordPaymentName(payment, locale) {
  const fundRecord = getFundRecord(payment);
  if (!fundRecord)
    return "";
  const name = getLocalizedValue(fundRecord.wallet_pass_name, locale);
  const code = maskMachineCode(fundRecord.code);
  if (!name && !code)
    return "";
  if (!code)
    return name;
  const fallbackName = getLocalizedValue(
    payment.name || payment.title || payment.payment_method_name || payment.method_name || payment.code,
    locale
  );
  return `${name || fallbackName}(${code})`;
}
function appendMachineCodeToName(name, payment) {
  const fundRecord = getFundRecord(payment);
  if (!(fundRecord == null ? void 0 : fundRecord.code))
    return name;
  return `${name}(${maskMachineCode(fundRecord.code)})`;
}
function paymentMethodName(payment, locale) {
  const fundRecordName = getFundRecordPaymentName(payment, locale);
  if (fundRecordName)
    return fundRecordName;
  const raw = payment.name || payment.title || payment.payment_method_name || payment.method_name;
  if (raw)
    return appendMachineCodeToName(getLocalizedValue(raw, locale), payment);
  const code = stringify(payment.code || payment.type || payment.payment_method || payment.method).toLowerCase();
  if (code.includes("cash"))
    return label(locale, "cash");
  if (code.includes("eftpos") || code.includes("card"))
    return label(locale, "eftpos");
  if (code.includes("wallet"))
    return label(locale, "wallet");
  if (code.includes("gift"))
    return label(locale, "giftCard");
  return stringify(payment.code || payment.type || payment.payment_method || payment.method);
}
function getSummary(order) {
  return order.summary && typeof order.summary === "object" ? order.summary : order;
}
function getCurrencySymbol(order, shopInfo) {
  return stringify(order.currency_symbol || (shopInfo == null ? void 0 : shopInfo.currency_symbol) || order.shop_symbol || "$") || "$";
}
function resolveLocales(shopInfo, locales) {
  const preferred = [
    ...locales || [],
    shopInfo.primary_locale,
    ...DEFAULT_LOCALES
  ].filter(Boolean);
  return Array.from(new Set(preferred.map(normalizeLocaleKey)));
}
function normalizeLocaleKey(locale) {
  return locale.replace("-", "_");
}
function label(locale, key) {
  var _a;
  return ((_a = LABELS[locale]) == null ? void 0 : _a[key]) || LABELS.en[key] || key;
}
function getLocalizedValue(value, locale) {
  if (value === void 0 || value === null)
    return "";
  if (typeof value !== "object")
    return stringify(value);
  const dashedLocale = locale.replace("_", "-");
  return stringify(
    value[locale] ?? value[dashedLocale] ?? value.default ?? value.en ?? value.zh_CN ?? value["zh-CN"] ?? Object.values(value).find((item) => typeof item === "string" || typeof item === "number") ?? ""
  );
}
function buildShopAddress(shopInfo) {
  return [
    shopInfo.address_street,
    shopInfo.address_detail,
    shopInfo.city,
    shopInfo.province,
    shopInfo.country,
    shopInfo.zip
  ].filter(Boolean).join(", ");
}
function formatDateTime(value, locale) {
  const date = (0, import_dayjs.default)(value);
  if (!date.isValid())
    return stringify(value);
  if (locale === "en")
    return date.format("HH:mm:ss DD/MM/YYYY");
  return date.format("YYYY/MM/DD HH:mm:ss");
}
function formatMoney(value, currencySymbol) {
  if (value instanceof import_decimal.default)
    return `${currencySymbol}${value.toFixed(2)}`;
  if (typeof value === "string" && value.trim().startsWith(currencySymbol))
    return value;
  const amount = new import_decimal.default(toMoneyNumber(value));
  return `${currencySymbol}${amount.toFixed(2)}`;
}
function sumPayments(payments) {
  return normalizeArray(payments).filter((payment) => isPrintablePayment(payment)).reduce((sum, payment) => {
    return sum.plus(toMoneyNumber(payment.amount ?? payment.origin_amount));
  }, new import_decimal.default(0));
}
function isPrintablePayment(payment) {
  const status = stringify(payment.status).toLowerCase();
  if (!status)
    return true;
  return ["paid", "success", "succeeded", "completed"].includes(status);
}
function normalizeArray(value) {
  return Array.isArray(value) ? value : [];
}
function isNonZero(value) {
  return !new import_decimal.default(toMoneyNumber(value)).isZero();
}
function toMoneyNumber(value) {
  if (value instanceof import_decimal.default)
    return value.toString();
  if (typeof value === "number")
    return Number.isFinite(value) ? value : 0;
  if (typeof value !== "string")
    return 0;
  const normalized = value.replace(/[^\d.-]/g, "");
  return normalized || 0;
}
function toNumber(value, fallback) {
  const numberValue = Number(value);
  return Number.isFinite(numberValue) ? numberValue : fallback;
}
function stringify(value) {
  if (value === void 0 || value === null)
    return "";
  return String(value);
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  buildSmallTicketData,
  hasSmallTicketData
});
