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/modules/order/utils/filterBookings.ts
var filterBookings_exports = {};
__export(filterBookings_exports, {
  filterBookings: () => filterBookings,
  filterBookingsFromOrders: () => filterBookingsFromOrders,
  flattenOrdersToBookings: () => flattenOrdersToBookings,
  productsForBooking: () => productsForBooking,
  sortBookings: () => sortBookings
});
module.exports = __toCommonJS(filterBookings_exports);
var import_dayjs = __toESM(require("dayjs"));
function getBookingAppointmentStatus(booking) {
  return String(booking.appointment_status ?? booking.status ?? "");
}
function toTimestamp(value) {
  if (value === void 0 || value === null || value === "")
    return 0;
  if (typeof value === "number")
    return value;
  const d = (0, import_dayjs.default)(value);
  return d.isValid() ? d.valueOf() : 0;
}
var DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
function toRangeBoundary(value, isEnd) {
  if (value === void 0 || value === null || value === "")
    return 0;
  if (typeof value === "number")
    return value;
  const str = String(value).trim();
  const d = (0, import_dayjs.default)(str);
  if (!d.isValid())
    return 0;
  if (DATE_ONLY_RE.test(str)) {
    return (isEnd ? d.endOf("day") : d.startOf("day")).valueOf();
  }
  return d.valueOf();
}
function bookingDateTimeString(datePart, timePart) {
  const d = (datePart ?? "").trim();
  let t = (timePart ?? "").trim();
  if (t && /^\d{1,2}:\d{2}$/.test(t)) {
    t = `${t}:00`;
  }
  return `${d} ${t}`.trim();
}
function parseDateRange(range) {
  if (!Array.isArray(range) || range.length < 2)
    return null;
  const start = toRangeBoundary(range[0], false);
  const end = toRangeBoundary(range[1], true);
  if (!start && !end)
    return null;
  return [start, end];
}
function parseNumberRange(range) {
  if (!Array.isArray(range) || range.length < 2)
    return null;
  const min = Number(range[0]);
  const max = Number(range[1]);
  if (isNaN(min) || isNaN(max))
    return null;
  return [min, max];
}
function prepareFilters(f) {
  var _a, _b, _c, _d, _e, _f;
  const hasCustomerId = f.customer_id !== void 0 && f.customer_id !== null;
  return {
    orderPaymentStatusSet: ((_a = f.order_payment_status) == null ? void 0 : _a.length) ? new Set(f.order_payment_status) : null,
    orderStatusSet: ((_b = f.order_status) == null ? void 0 : _b.length) ? new Set(f.order_status) : null,
    orderSalesChannelSet: ((_c = f.order_sales_channel) == null ? void 0 : _c.length) ? new Set(f.order_sales_channel) : null,
    paymentMethodSet: ((_d = f.payment_method) == null ? void 0 : _d.length) ? new Set(f.payment_method) : null,
    appointmentStatusSet: ((_e = f.appointment_status) == null ? void 0 : _e.length) ? new Set(f.appointment_status) : null,
    formRecordIdSet: ((_f = f.form_record_ids) == null ? void 0 : _f.length) ? new Set(f.form_record_ids) : null,
    hasCustomerId,
    customerIdStr: hasCustomerId ? String(f.customer_id) : "",
    hasBusinessCode: !!f.business_code,
    businessCode: f.business_code,
    bookingTimeRange: parseDateRange(f.sales_time_between),
    createdAtRange: parseDateRange(f.created_at_between),
    updatedAtRange: parseDateRange(f.updated_at_between),
    numberRange: parseNumberRange(f.number_between),
    totalAmountRange: Array.isArray(f.total_amount_between) && f.total_amount_between.length === 2 ? f.total_amount_between : null,
    keywordLower: f.keyword ? f.keyword.toLowerCase() : "",
    afterExecutionTimeMs: (() => {
      const raw = f.after_execution_time;
      if (raw === void 0 || raw === null || raw === "")
        return null;
      const ms = toTimestamp(raw);
      return Number.isFinite(ms) ? ms : null;
    })(),
    enableChildBookingFilter: f.child_booking === 1
  };
}
function matchOrder(order, ctx) {
  var _a;
  if (ctx.hasBusinessCode && order.business_code !== ctx.businessCode)
    return false;
  if (ctx.hasCustomerId && String(order.customer_id) !== ctx.customerIdStr)
    return false;
  if (ctx.orderPaymentStatusSet && !ctx.orderPaymentStatusSet.has(order.payment_status))
    return false;
  if (ctx.orderStatusSet && !ctx.orderStatusSet.has(order.status))
    return false;
  if (ctx.orderSalesChannelSet && !ctx.orderSalesChannelSet.has(order.order_sales_channel))
    return false;
  if (ctx.paymentMethodSet) {
    const pm = order.payments;
    if (!Array.isArray(pm) || pm.length === 0)
      return false;
    let matched = false;
    for (let k = 0; k < pm.length; k++) {
      if (ctx.paymentMethodSet.has(pm[k].code)) {
        matched = true;
        break;
      }
    }
    if (!matched)
      return false;
  }
  if (ctx.createdAtRange) {
    const ts = toTimestamp(order.created_at);
    if (ts < ctx.createdAtRange[0] || ts > ctx.createdAtRange[1])
      return false;
  }
  if (ctx.updatedAtRange) {
    const ts = toTimestamp(order.updated_at);
    if (ts < ctx.updatedAtRange[0] || ts > ctx.updatedAtRange[1])
      return false;
  }
  if (ctx.totalAmountRange) {
    const raw = ((_a = order.summary) == null ? void 0 : _a.total_amount) ?? order.total_amount;
    const amt = Number(raw);
    if (isNaN(amt))
      return false;
    if (ctx.totalAmountRange[0] != null && amt < ctx.totalAmountRange[0])
      return false;
    if (ctx.totalAmountRange[1] != null && amt > ctx.totalAmountRange[1])
      return false;
  }
  return true;
}
function matchBooking(booking, orderInfo, ctx) {
  if (ctx.enableChildBookingFilter) {
    const parentId = Number(booking.parent_id ?? 0);
    const itemType = String(booking.item_type ?? "");
    const isMatched = parentId !== 0 && itemType !== "recurring_booking" || parentId === 0 && itemType === "recurring_booking";
    if (!isMatched)
      return false;
  }
  if (ctx.appointmentStatusSet && !ctx.appointmentStatusSet.has(getBookingAppointmentStatus(booking)))
    return false;
  if (ctx.bookingTimeRange) {
    const ts = toTimestamp(bookingDateTimeString(booking.start_date, booking.start_time));
    if (ts < ctx.bookingTimeRange[0] || ts > ctx.bookingTimeRange[1])
      return false;
  }
  if (ctx.afterExecutionTimeMs != null) {
    const bookingStartMs = toTimestamp(bookingDateTimeString(booking.start_date, booking.start_time));
    if (!Number.isFinite(bookingStartMs) || bookingStartMs < ctx.afterExecutionTimeMs)
      return false;
  }
  if (ctx.numberRange) {
    const num = Number(booking.number);
    if (isNaN(num) || num < ctx.numberRange[0] || num > ctx.numberRange[1])
      return false;
  }
  if (ctx.formRecordIdSet) {
    let formMatched = false;
    const resources = booking.resources;
    if (Array.isArray(resources)) {
      for (let r = 0; r < resources.length; r++) {
        if (resources[r].relation_type === "form" && ctx.formRecordIdSet.has(resources[r].relation_id)) {
          formMatched = true;
          break;
        }
      }
    }
    if (!formMatched && booking.relation_type === "form" && booking.relation_id && booking.relation_id > 0) {
      formMatched = ctx.formRecordIdSet.has(booking.relation_id);
    }
    if (!formMatched)
      return false;
  }
  if (ctx.keywordLower) {
    const target = orderInfo ? { ...booking, order: orderInfo } : booking;
    const str = JSON.stringify(target).toLowerCase();
    if (!str.includes(ctx.keywordLower))
      return false;
  }
  return true;
}
function productsForBooking(order, booking) {
  var _a;
  const products = order.products;
  if (!Array.isArray(products) || products.length === 0)
    return [];
  const bookingEventId = booking.schedule_event_id;
  const byDetailId = /* @__PURE__ */ new Map();
  for (let i = 0, len = products.length; i < len; i++) {
    const p = products[i];
    const oid = p.order_detail_id;
    if (oid === void 0 || oid === null)
      continue;
    const detailId = Number(oid);
    if (Number.isNaN(detailId))
      continue;
    byDetailId.set(detailId, p);
  }
  const seen = /* @__PURE__ */ new Set();
  const out = [];
  for (let i = 0, len = products.length; i < len; i++) {
    const p = products[i];
    const oid = p.order_detail_id;
    if (oid === void 0 || oid === null)
      continue;
    const detailId = Number(oid);
    if (Number.isNaN(detailId))
      continue;
    if (bookingEventId !== void 0 && bookingEventId !== null && p.schedule_event_id !== void 0 && p.schedule_event_id !== null && Number(p.schedule_event_id) === Number(bookingEventId)) {
      if (!seen.has(detailId)) {
        seen.add(detailId);
        out.push(p);
      }
    }
  }
  const relationItems = booking.relation_items;
  if (Array.isArray(relationItems) && relationItems.length > 0) {
    for (let r = 0, rLen = relationItems.length; r < rLen; r++) {
      const rid = (_a = relationItems[r]) == null ? void 0 : _a.resource_id;
      if (rid === void 0 || rid === null)
        continue;
      const detailId = Number(rid);
      if (Number.isNaN(detailId) || seen.has(detailId))
        continue;
      const line = byDetailId.get(detailId);
      if (line) {
        seen.add(detailId);
        out.push(line);
      }
    }
  }
  return out;
}
function flattenOrdersToBookings(orders) {
  if (!orders || !Array.isArray(orders))
    return [];
  const result = [];
  for (let i = 0, len = orders.length; i < len; i++) {
    const order = orders[i];
    const bookings = order.bookings;
    if (!Array.isArray(bookings) || bookings.length === 0)
      continue;
    const { bookings: _omit, ...orderInfo } = order;
    for (let j = 0, bLen = bookings.length; j < bLen; j++) {
      const booking = bookings[j];
      result.push({
        ...booking,
        order: orderInfo,
        products: order.products
      });
    }
  }
  return result;
}
function filterBookingsFromOrders(orders, filters) {
  const f = filters || {};
  if (!orders || !Array.isArray(orders)) {
    return { list: [], count: 0, size: 0, skip: 0 };
  }
  const size = f.num || 20;
  const page = f.skip || 1;
  const startIndex = (page - 1) * size;
  const ctx = prepareFilters(f);
  let totalCount = 0;
  const paginatedList = [];
  for (let i = 0, oLen = orders.length; i < oLen; i++) {
    const order = orders[i];
    const bookings = order.bookings;
    if (!Array.isArray(bookings) || bookings.length === 0)
      continue;
    if (!matchOrder(order, ctx))
      continue;
    let orderInfo = null;
    for (let j = 0, bLen = bookings.length; j < bLen; j++) {
      const booking = bookings[j];
      if (ctx.keywordLower && !orderInfo) {
        const { bookings: _omit, ...rest } = order;
        orderInfo = rest;
      }
      if (!matchBooking(booking, orderInfo, ctx))
        continue;
      if (totalCount >= startIndex && paginatedList.length < size) {
        if (!orderInfo) {
          const { bookings: _omit, ...rest } = order;
          orderInfo = rest;
        }
        paginatedList.push({
          ...booking,
          order: orderInfo,
          products: order.products
        });
      }
      totalCount++;
    }
  }
  return {
    list: paginatedList,
    count: totalCount,
    size,
    skip: page
  };
}
function sortBookings(result, filters) {
  const f = filters || {};
  const orderBy = f.order_by;
  if (!orderBy)
    return result;
  const separatorIdx = orderBy.lastIndexOf(":");
  if (separatorIdx === -1)
    return result;
  const field = orderBy.slice(0, separatorIdx);
  const direction = orderBy.slice(separatorIdx + 1);
  if (direction !== "asc" && direction !== "desc")
    return result;
  const multiplier = direction === "asc" ? 1 : -1;
  const getTimestamp = (booking) => {
    switch (field) {
      case "start_at":
        return toTimestamp(bookingDateTimeString(booking.start_date, booking.start_time));
      case "end_at":
        return toTimestamp(bookingDateTimeString(booking.end_date, booking.end_time));
      case "created_at":
        return toTimestamp(booking.order.created_at);
      case "updated_at":
        return toTimestamp(booking.order.updated_at);
      default:
        return 0;
    }
  };
  const sorted = result.list.slice().sort((a, b) => {
    return (getTimestamp(a) - getTimestamp(b)) * multiplier;
  });
  return { ...result, list: sorted };
}
function filterBookings(bookings, filters) {
  const f = filters || {};
  if (!bookings || !Array.isArray(bookings)) {
    return { list: [], count: 0, size: 0, skip: 0 };
  }
  const size = f.num || 20;
  const page = f.skip || 1;
  const startIndex = (page - 1) * size;
  const ctx = prepareFilters(f);
  let totalCount = 0;
  const paginatedList = [];
  for (let i = 0, len = bookings.length; i < len; i++) {
    const booking = bookings[i];
    const order = booking.order;
    if (!matchOrder(order, ctx))
      continue;
    if (!matchBooking(booking, order, ctx))
      continue;
    if (totalCount >= startIndex && paginatedList.length < size) {
      paginatedList.push({
        ...booking,
        products: booking.order.products
      });
    }
    totalCount++;
  }
  return {
    list: paginatedList,
    count: totalCount,
    size,
    skip: page
  };
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  filterBookings,
  filterBookingsFromOrders,
  flattenOrdersToBookings,
  productsForBooking,
  sortBookings
});
