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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
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/index.ts
var server_exports = {};
__export(server_exports, {
  default: () => server_default
});
module.exports = __toCommonJS(server_exports);
var import_dayjs = __toESM(require("dayjs"));
var import_products = require("./modules/products");
var import_menu = require("./modules/menu");
var import_quotation = require("./modules/quotation");
var import_schedule = require("./modules/schedule");
var import_resource = require("./modules/resource");
var import_floor_plan = require("./modules/floor-plan");
var import_types = require("./modules/floor-plan/types");
var import_schedule2 = require("./utils/schedule");
var import_types2 = require("./modules/products/types");
var import_product = require("./utils/product");
var import_order = require("./modules/order");
var import_types3 = require("./modules/order/types");
var import_filterOrders = require("./modules/order/utils/filterOrders");
var import_filterBookings = require("./modules/order/utils/filterBookings");
__reExport(server_exports, require("./modules"), module.exports);
var Server = class {
  constructor(core) {
    /** GET 前缀路由（最长前缀优先匹配） */
    this.prefixRouterGet = [];
    // 路由注册表
    this.router = {
      get: {},
      post: {},
      put: {},
      remove: {}
    };
    // ---- 商品查询订阅者 ----
    this.productQuerySubscribers = /* @__PURE__ */ new Map();
    // ---- 订单 / 预约列表查询订阅者 ----
    this.orderQuerySubscribers = /* @__PURE__ */ new Map();
    this.bookingQuerySubscribers = /* @__PURE__ */ new Map();
    this.bookingRemoteQuerySubscribers = /* @__PURE__ */ new Map();
    this.bookingRemoteCache = /* @__PURE__ */ new Map();
    this.BOOKING_REMOTE_CACHE_TTL_MS = 5 * 60 * 1e3;
    this.BOOKING_REMOTE_CACHE_MAX_ENTRIES = 80;
    this.floorPlanQuerySubscribers = /* @__PURE__ */ new Map();
    // 模块注册表 - 定义所有可用的模块配置
    this.moduleRegistry = {
      products: {
        name: "products",
        moduleClass: import_products.ProductsModule,
        moduleName: "server_products",
        version: "1.0.0",
        defaultStore: {
          list: [],
          selectProducts: []
        }
      },
      menu: {
        name: "menu",
        moduleClass: import_menu.MenuModule,
        moduleName: "server_menu",
        version: "1.0.0",
        defaultStore: {
          menuList: []
        }
      },
      quotation: {
        name: "quotation",
        moduleClass: import_quotation.QuotationModule,
        moduleName: "server_quotation",
        version: "1.0.0",
        defaultStore: {
          quotationList: []
        }
      },
      schedule: {
        name: "schedule",
        moduleClass: import_schedule.ScheduleModuleEx,
        moduleName: "server_schedule",
        version: "1.1.0",
        defaultStore: {
          scheduleList: [],
          availabilityDateList: [],
          otherProductsIds: []
        }
      },
      order: {
        name: "order",
        moduleClass: import_order.OrderModule,
        moduleName: "server_order",
        version: "1.0.0",
        defaultStore: {
          list: []
        }
      },
      resource: {
        name: "resource",
        moduleClass: import_resource.ResourceModule,
        moduleName: "server_resource",
        version: "1.0.0",
        defaultStore: {
          list: [],
          map: /* @__PURE__ */ new Map(),
          bookings: []
        }
      },
      floor_plan: {
        name: "floor_plan",
        moduleClass: import_floor_plan.FloorPlanModule,
        moduleName: "server_floor_plan",
        version: "1.0.0",
        defaultStore: {
          list: [],
          map: /* @__PURE__ */ new Map(),
          codeMap: /* @__PURE__ */ new Map()
        }
      }
    };
    /**
     * 处理商品查询请求
     * 存储订阅者信息，便于数据变更时推送最新结果
     */
    this.handleProductQuery = async ({ url, method, data, config }) => {
      console.log("[Server] handleProductQuery:", url, method, data, config);
      const { menu_list_ids, schedule_datetime, schedule_date, customer_id } = data;
      const { callback, subscriberId } = config || {};
      this.logInfo("handleProductQuery: 开始处理商品查询请求", {
        menu_list_ids,
        schedule_datetime,
        schedule_date,
        customer_id
      });
      if (subscriberId && typeof callback === "function") {
        this.productQuerySubscribers.set(subscriberId, {
          callback,
          context: { menu_list_ids, schedule_date, schedule_datetime, customer_id }
        });
        this.logInfo("handleProductQuery: 已注册订阅者", {
          subscriberId,
          totalSubscribers: this.productQuerySubscribers.size
        });
      }
      return this.computeProductQueryResult({ menu_list_ids, schedule_date, schedule_datetime, customer_id });
    };
    /**
     * 按商品 id 查询单条（GET /shop/product/query/:productId）
     * schedule_date 必填：query 或 data；schedule_datetime 可选。不走订阅。
     */
    this.handleProductQueryById = async ({ path, method, data, url }) => {
      const pathname = this.parseRequestPath(url || "", path);
      const idMatch = pathname.match(/^\/shop\/product\/query\/(\d+)$/);
      const productId = idMatch ? Number(idMatch[1]) : NaN;
      console.log("[Server] handleProductQueryById:", pathname, method, data);
      if (!Number.isFinite(productId)) {
        this.logWarning("handleProductQueryById: 无效的商品 id", { path: pathname });
        return {
          code: 400,
          message: "无效的商品路径",
          status: false,
          data: { item: null }
        };
      }
      const scheduleDateFromData = data && typeof data === "object" && typeof data.schedule_date === "string" ? data.schedule_date.trim() : "";
      const schedule_date = scheduleDateFromData || (this.extractQueryParam(url || "", "schedule_date") || "").trim() || (0, import_dayjs.default)().format("YYYY-MM-DD");
      if (!schedule_date) {
        this.logWarning("handleProductQueryById: 缺少 schedule_date", { productId });
        return {
          code: 400,
          message: "schedule_date 为必填（query 或 data）",
          status: false,
          data: null
        };
      }
      const scheduleDtFromData = data && typeof data === "object" && typeof data.schedule_datetime === "string" ? data.schedule_datetime.trim() : "";
      const scheduleDtFromUrl = (this.extractQueryParam(url || "", "schedule_datetime") || "").trim();
      const scheduleDatetime = scheduleDtFromData || scheduleDtFromUrl || `${schedule_date}T00:00:00`;
      this.logInfo("handleProductQueryById: 开始", {
        productId,
        schedule_date,
        schedule_datetime: scheduleDatetime
      });
      return this.computeProductQueryResult({
        schedule_date,
        schedule_datetime: scheduleDatetime,
        product_id: productId
      });
    };
    /**
     * 取消商品查询订阅（HTTP 路由入口）
     */
    this.handleUnsubscribeProductQuery = async ({ data }) => {
      const { subscriberId } = data || {};
      this.removeProductQuerySubscriber(subscriberId);
      return { code: 200, message: "ok", status: true };
    };
    /**
     * 处理订单列表查询
     * 存储订阅者信息，本地计算结果；数据变更时通过 callback 推送
     */
    this.handleOrderList = async ({ url, method, data, config }) => {
      console.log("[Server] handleOrderList:", url, method, data, config);
      const queryPayload = data && typeof data === "object" ? { ...data } : {};
      const { callback, subscriberId } = config || {};
      const useLocal = this.shouldUseLocalOrderQuery(queryPayload);
      this.logInfo("handleOrderList: 开始处理订单列表请求", {
        data: queryPayload,
        useLocal
      });
      if (useLocal) {
        if (subscriberId && typeof callback === "function") {
          this.orderQuerySubscribers.set(subscriberId, {
            callback,
            context: queryPayload
          });
          this.logInfo("handleOrderList: 已注册订阅者", {
            subscriberId,
            totalSubscribers: this.orderQuerySubscribers.size
          });
        }
        return this.computeOrderQueryResult(queryPayload);
      }
      if (subscriberId) {
        this.orderQuerySubscribers.delete(subscriberId);
        this.logInfo("handleOrderList: 已清理订阅者（走远端）", {
          subscriberId,
          remaining: this.orderQuerySubscribers.size
        });
      }
      return this.fetchOrderListFromAPI(queryPayload);
    };
    /**
     * 取消订单列表查询订阅（HTTP 路由入口）
     */
    this.handleUnsubscribeOrderQuery = async ({ data }) => {
      const { subscriberId } = data || {};
      if (subscriberId) {
        this.orderQuerySubscribers.delete(subscriberId);
        this.logInfo("handleUnsubscribeOrderQuery: 已移除订阅者", {
          subscriberId,
          remaining: this.orderQuerySubscribers.size
        });
      }
      return { code: 200, message: "ok", status: true };
    };
    /**
     * 日历（compact_fields）场景下要直接在 SSE 层排除的订单类型：
     * 这些类型不会出现在日历上，拉取它们只会浪费带宽并增加前端过滤成本。
     */
    this.BOOKING_SALES_COMPACT_EXCLUDE_TYPES = [
      "virtual",
      "shipping",
      "delivery",
      "pickup"
    ];
    /**
     * 处理预约列表查询
     * 今天：注册订阅者 + 本地数据筛选；非今天：清理订阅者 + 走真实 API
     */
    this.handleBookingList = async ({ url, method, data, config }) => {
      console.log("[Server] handleBookingList:", url, method, data, config);
      const queryPayload = data && typeof data === "object" ? { ...data } : {};
      const { callback, subscriberId } = config || {};
      const useLocal = this.shouldUseLocalBookingQuery(queryPayload);
      this.logInfo("handleBookingList: 开始处理预约列表请求", {
        data: queryPayload,
        useLocal
      });
      if (useLocal) {
        if (subscriberId) {
          this.bookingRemoteQuerySubscribers.delete(subscriberId);
        }
        if (subscriberId && typeof callback === "function") {
          this.bookingQuerySubscribers.set(subscriberId, {
            callback,
            context: queryPayload
          });
          this.logInfo("handleBookingList: 已注册订阅者（今天）", {
            subscriberId,
            totalSubscribers: this.bookingQuerySubscribers.size
          });
        }
        return this.computeBookingQueryResult(queryPayload);
      } else {
        if (subscriberId) {
          this.bookingQuerySubscribers.delete(subscriberId);
        }
        if (subscriberId && typeof callback === "function") {
          const withFields = this.resolveBookingSalesWith(queryPayload);
          const requestPayload = this.normalizeBookingRemoteQueryPayload(
            queryPayload,
            withFields
          );
          const cacheKey = this.buildBookingRemoteCacheKey(requestPayload);
          this.bookingRemoteQuerySubscribers.set(subscriberId, {
            callback,
            context: queryPayload,
            cacheKey
          });
          this.logInfo("handleBookingList: 已注册订阅者（非今天）", {
            subscriberId,
            cacheKey,
            totalSubscribers: this.bookingRemoteQuerySubscribers.size
          });
        }
        if (subscriberId) {
          this.logInfo("handleBookingList: 已清理订阅者（非今天）", {
            subscriberId,
            remaining: this.bookingQuerySubscribers.size
          });
        }
        return this.fetchBookingListFromAPI(queryPayload);
      }
    };
    /**
     * 处理资源列表查询
     * 转发到资源模块去
     */
    this.handleResourceList = async ({ url, method, data, config }) => {
      var _a;
      console.log("[Server] handleResourceList:", url, method, data, config);
      const list = (_a = this.resource) == null ? void 0 : _a.getResources({
        skip: (data == null ? void 0 : data.skip) || 1,
        num: (data == null ? void 0 : data.num) || 10
      });
      this.logInfo("Server 劫持 Resource 接口：handleResourceList: 资源列表查询结果", { list });
      return {
        code: 200,
        data: { list, count: (list == null ? void 0 : list.length) || 0 },
        message: "",
        status: true
      };
    };
    /**
     * 代理刷新 / 合并订单到本地（单笔 / 批量二合一）：
     * - 入参（GET query 或 data 任一）：
     *   - `order_id`：单笔模式，原有行为
     *   - `order_ids`：批量模式，逗号分隔的 id 列表（如 `?order_ids=1,2,3`），数组也兼容
     *   - 同时存在时优先批量
     * - 单笔流程：后端 /order/sales/{id}?with[]=all → 本地有则覆盖、无则 merge → 落 SQLite → emit onOrdersChanged
     * - 批量流程：并发拉取每笔详情 → 一次性 `upsertOrdersFromRemote` 合并写入 → 仅 emit 一次 onOrdersChanged，
     *   单笔失败不影响其他成功项；返回 { overwritten, inserted, failed }
     * - 监听级联：onOrdersChanged 触发订单 / 预约 / bookingRemoteCache 三路订阅者推送
     *
     * @example 单笔：GET /update/localOrder?order_id=96971
     * @example 批量：GET /update/localOrder?order_ids=96971,96972,96973
     */
    this.handleUpdateLocalOrder = async ({ url, data }) => {
      var _a;
      const batchIds = this.parseOrderIdsParam(url, data);
      if (batchIds.length > 0) {
        return this.handleUpdateLocalOrdersBatch(batchIds);
      }
      const rawOrderId = (data && typeof data === "object" ? data.order_id : void 0) ?? this.extractQueryParam(url, "order_id");
      const orderId = rawOrderId === void 0 || rawOrderId === null || rawOrderId === "" ? null : String(rawOrderId).trim();
      this.logInfo("handleUpdateLocalOrder: 开始处理", { url, orderId });
      if (!orderId) {
        this.logWarning("handleUpdateLocalOrder: order_id 缺失", { url, data });
        return { code: 400, status: false, message: "order_id 缺失", data: null };
      }
      if (!this.order) {
        this.logError("handleUpdateLocalOrder: Order 模块未注册");
        return { code: 500, status: false, message: "Order 模块未注册", data: null };
      }
      if (!((_a = this.app) == null ? void 0 : _a.request)) {
        this.logError("handleUpdateLocalOrder: app.request 不可用");
        return { code: 500, status: false, message: "app.request 不可用", data: null };
      }
      const backendPath = `/shop/order/sales/${encodeURIComponent(
        orderId
      )}?with%5B%5D=all`;
      try {
        const response = await this.app.request.get(backendPath, void 0, {
          isShopApi: true
        });
        const fresh = (response == null ? void 0 : response.data) ?? response;
        if (!fresh || typeof fresh !== "object" || fresh.order_id == null) {
          this.logError("handleUpdateLocalOrder: 后端返回订单为空", {
            orderId,
            backendPath
          });
          return {
            code: 500,
            status: false,
            message: "后端返回订单为空",
            data: null
          };
        }
        const exists = !!this.order.getOrderByOrderId(orderId);
        if (exists) {
          const { overwritten } = await this.order.overwriteExistingOrder(
            fresh
          );
          this.logInfo("handleUpdateLocalOrder: 覆盖完成", {
            orderId,
            overwritten
          });
          return {
            code: 200,
            status: true,
            message: "",
            data: { overwritten, inserted: false, order_id: orderId }
          };
        }
        await this.order.upsertOrdersFromRemote([fresh]);
        this.logInfo("handleUpdateLocalOrder: 本地合并新订单完成", { orderId });
        return {
          code: 200,
          status: true,
          message: "",
          data: { overwritten: false, inserted: true, order_id: orderId }
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError("handleUpdateLocalOrder: 请求失败", {
          orderId,
          backendPath,
          error: errorMessage
        });
        return {
          code: 500,
          status: false,
          message: errorMessage,
          data: null
        };
      }
    };
    this.handleOrderSalesDetail = async ({ url, data, path }) => {
      var _a;
      const requestPath = this.parseRequestPath(url, path);
      const orderId = this.extractOrderSalesDetailId(requestPath);
      this.logInfo("handleOrderSalesDetail: 开始处理", { url, path: requestPath, orderId });
      if (!orderId) {
        this.logWarning("handleOrderSalesDetail: order_id 缺失", { url, path: requestPath });
        return { code: 400, status: false, message: "order_id 缺失", data: null };
      }
      if (!this.order) {
        this.logError("handleOrderSalesDetail: Order 模块未注册");
        return { code: 500, status: false, message: "Order 模块未注册", data: null };
      }
      const localOrder = await this.order.getLocalOrderByOrderId(orderId);
      if (localOrder) {
        this.logInfo("handleOrderSalesDetail: 命中本地订单", { orderId });
        return {
          code: 200,
          status: true,
          message: "",
          data: localOrder
        };
      }
      if (!((_a = this.app) == null ? void 0 : _a.request)) {
        this.logError("handleOrderSalesDetail: app.request 不可用");
        return { code: 500, status: false, message: "app.request 不可用", data: null };
      }
      const backendPath = this.buildOrderSalesDetailBackendPath(orderId, data);
      try {
        const response = await this.app.request.get(backendPath, {
          lookup_mode: "multi"
        }, {
          isShopApi: true,
          customToast: () => {
          }
        });
        const fresh = (response == null ? void 0 : response.data) ?? response;
        if (!fresh || typeof fresh !== "object" || fresh.order_id == null) {
          this.logError("handleOrderSalesDetail: 后端返回订单为空", {
            orderId,
            backendPath
          });
          return {
            code: 500,
            status: false,
            message: "后端返回订单为空",
            data: null
          };
        }
        await this.order.upsertOrdersFromRemote([fresh]);
        const savedOrder = await this.order.getLocalOrderByOrderId(orderId);
        if (!savedOrder) {
          this.logError("handleOrderSalesDetail: 订单写入后回读失败", { orderId });
          return {
            code: 500,
            status: false,
            message: "订单写入后回读失败",
            data: null
          };
        }
        this.logInfo("handleOrderSalesDetail: 远端订单已同步到本地", { orderId });
        return {
          code: 200,
          status: true,
          message: "",
          data: savedOrder
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError("handleOrderSalesDetail: 请求失败", {
          orderId,
          backendPath,
          error: errorMessage
        });
        return {
          code: 500,
          status: false,
          message: errorMessage,
          data: null
        };
      }
    };
    /**
     * GET /shop/schedule/floor-plan* 前缀路由：读本地 store；支持 subscriberId + callback 订阅更新
     */
    this.handleFloorPlanGet = async ({ url, data, config, path: routePath }) => {
      const base = "/shop/schedule/floor-plan";
      const path = this.parseRequestPath(url, routePath);
      if (path === `${base}/unsubscribe`) {
        const subscriberId2 = data == null ? void 0 : data.subscriberId;
        if (subscriberId2) {
          this.floorPlanQuerySubscribers.delete(subscriberId2);
          this.logInfo("handleFloorPlanGet: 已取消订阅", {
            subscriberId: subscriberId2,
            remaining: this.floorPlanQuerySubscribers.size
          });
        }
        return { code: 200, message: "ok", status: true };
      }
      const { callback, subscriberId } = config || {};
      const ctx = this.resolveFloorPlanQueryContext(path, base);
      if (!ctx) {
        return { status: false, code: 404, message: "Not Found", data: null };
      }
      if (subscriberId && typeof callback === "function") {
        this.floorPlanQuerySubscribers.set(subscriberId, { callback, context: ctx });
        this.logInfo("handleFloorPlanGet: 已注册订阅者", {
          subscriberId,
          kind: ctx.kind,
          total: this.floorPlanQuerySubscribers.size
        });
      }
      return this.computeFloorPlanQueryResult(ctx);
    };
    /**
     * 取消预约列表查询订阅（HTTP 路由入口）
     */
    this.handleUnsubscribeBookingQuery = async ({ data }) => {
      const { subscriberId } = data || {};
      if (subscriberId) {
        this.bookingQuerySubscribers.delete(subscriberId);
        this.bookingRemoteQuerySubscribers.delete(subscriberId);
        this.logInfo("handleUnsubscribeBookingQuery: 已移除订阅者", {
          subscriberId,
          remainingLocal: this.bookingQuerySubscribers.size,
          remainingRemote: this.bookingRemoteQuerySubscribers.size
        });
      }
      return { code: 200, message: "ok", status: true };
    };
    /**
     * 处理获取日程时间段点的请求
     * 通过餐牌ID列表获取所有相关日程的时间段点
     */
    this.handleGetScheduleTimePoints = async ({ url, method, data, config }) => {
      console.log("[Server] handleGetScheduleTimePoints:", url, method, data, config);
      const { menu_list_ids } = data;
      this.logInfo("handleGetScheduleTimePoints 开始处理", { menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0, menu_list_ids });
      if (!this.menu) {
        console.error("[Server] Menu 模块未注册");
        this.logError("handleGetScheduleTimePoints: Menu 模块未注册");
        return {
          code: 500,
          message: "Menu 模块未注册",
          data: [],
          status: false
        };
      }
      if (!this.schedule) {
        console.error("[Server] Schedule 模块未注册");
        this.logError("handleGetScheduleTimePoints: Schedule 模块未注册");
        return {
          code: 500,
          message: "Schedule 模块未注册",
          data: [],
          status: false
        };
      }
      if (!menu_list_ids || !Array.isArray(menu_list_ids) || menu_list_ids.length === 0) {
        console.error("[Server] menu_list_ids 参数无效");
        this.logWarning("handleGetScheduleTimePoints: menu_list_ids 参数无效", { menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0, menu_list_ids });
        return {
          code: 400,
          message: "menu_list_ids 参数无效",
          data: [],
          status: false
        };
      }
      try {
        const menuList = this.menu.getMenuByIds(menu_list_ids);
        console.log(`[Server] 找到 ${menuList.length} 个餐牌`);
        this.logInfo("handleGetScheduleTimePoints: 获取到餐牌列表", {
          requestedCount: menu_list_ids.length,
          foundCount: menuList.length,
          menu_list_ids,
          menuList
        });
        const scheduleIds = (0, import_schedule2.extractScheduleIdsFromMenus)(menuList);
        console.log(`[Server] 提取到 ${scheduleIds.length} 个日程ID:`, scheduleIds);
        this.logInfo("handleGetScheduleTimePoints: 提取到日程 IDs", {
          scheduleCount: scheduleIds.length
        });
        if (scheduleIds.length === 0) {
          this.logInfo("handleGetScheduleTimePoints: 没有找到相关日程", { menuListIdsCount: menu_list_ids.length });
          return {
            code: 200,
            message: "没有找到相关日程",
            data: [],
            status: true
          };
        }
        const scheduleList = this.schedule.getScheduleByIds(scheduleIds);
        console.log(`[Server] 找到 ${scheduleList.length} 个日程`);
        this.logInfo("handleGetScheduleTimePoints: 获取到日程详情", {
          requestedCount: scheduleIds.length,
          foundCount: scheduleList.length
        });
        const timePoints = (0, import_schedule2.extractTimePointsFromSchedules)(scheduleList);
        console.log(`[Server] 提取到 ${timePoints.length} 个时间点:`, timePoints);
        this.logInfo("handleGetScheduleTimePoints 处理完成", {
          menuListIdsCount: menu_list_ids.length,
          menuCount: menuList.length,
          scheduleCount: scheduleList.length,
          timePointCount: timePoints.length
        });
        return {
          code: 200,
          message: "获取成功",
          data: timePoints,
          status: true
        };
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : "未知错误";
        console.error("[Server] 获取日程时间点失败:", error);
        this.logError("handleGetScheduleTimePoints: 获取日程时间点失败", {
          menuListIdsCount: menu_list_ids.length,
          error: errorMessage
        });
        return {
          code: 500,
          message: `获取失败: ${errorMessage}`,
          data: [],
          status: false
        };
      }
    };
    var _a;
    this.core = core;
    const appPlugin = core.getPlugin("app");
    this.app = (appPlugin == null ? void 0 : appPlugin.getApp()) || null;
    this.logger = ((_a = this.app) == null ? void 0 : _a.logger) || null;
    console.log("[Server] Server 初始化", this.core);
    this.logInfo("Server 初始化", {
      hasApp: !!this.app,
      hasLogger: !!this.logger
    });
  }
  /**
   * 注册路由
   * @param routes 路由定义数组
   */
  registerRoutes(routes) {
    routes.forEach((route) => {
      const { method, path, handler } = route;
      if (!this.router[method]) {
        console.warn(`[Server] 不支持的 HTTP 方法: ${method}`);
        this.logWarning(`不支持的 HTTP 方法`, { method, path });
        return;
      }
      if (this.router[method][path]) {
        console.warn(`[Server] 路由已存在，将被覆盖: ${method.toUpperCase()} ${path}`);
        this.logWarning(`路由已存在，将被覆盖`, { method, path });
      }
      this.router[method][path] = handler;
      console.log(`[Server] 📝 注册路由: ${method.toUpperCase()} ${path}`);
      this.logInfo(`注册路由`, { method: method.toUpperCase(), path });
    });
  }
  /**
   * 注册前缀路由（仅 GET）。匹配规则：path === prefix 或 path 以 prefix + '/' 开头；最长前缀优先。
   */
  registerPrefixRoutes(routes) {
    for (const r of routes) {
      if (r.method !== "get") {
        this.logWarning("registerPrefixRoutes: 当前仅支持 GET", {
          method: r.method,
          prefix: r.prefix
        });
        continue;
      }
      this.prefixRouterGet.push({ prefix: r.prefix, handler: r.handler });
    }
    this.prefixRouterGet.sort((a, b) => b.prefix.length - a.prefix.length);
    this.logInfo("前缀 GET 路由已更新", { count: this.prefixRouterGet.length });
  }
  /**
   * 注册单个模块并自动注册其路由
   * @param module 模块实例
   * @param options 模块配置
   * @param moduleName 模块名称（用于日志）
   */
  async registerModuleWithRoutes(module2, options, moduleName) {
    this.logInfo(`开始注册模块: ${moduleName}`, { moduleName, options });
    await this.core.registerModule(module2, options);
    console.log(`[Server] ✅ ${moduleName} 模块已注册`);
    this.logInfo(`模块注册成功: ${moduleName}`, { moduleName });
    if (typeof module2.getRoutes === "function") {
      const routes = module2.getRoutes();
      if (routes && routes.length > 0) {
        this.registerRoutes(routes);
        this.logInfo(`模块路由已注册: ${moduleName}`, { moduleName, routesCount: routes.length });
      }
    }
  }
  /**
   * 根据模块名称注册单个模块
   * @param moduleConfig 模块配置（可以是字符串或配置对象）
   */
  async registerModuleByName(moduleConfig) {
    const moduleName = typeof moduleConfig === "string" ? moduleConfig : moduleConfig.name;
    const shouldPreload = typeof moduleConfig === "object" ? moduleConfig.preload !== false : true;
    const customConfig = typeof moduleConfig === "object" ? moduleConfig.config : {};
    this.logInfo(`解析模块配置: ${moduleName}`, {
      moduleName,
      shouldPreload,
      customConfig
    });
    const registryConfig = this.moduleRegistry[moduleName];
    if (!registryConfig) {
      this.logError(`未找到模块配置: ${moduleName}`, { moduleName });
      throw new Error(`[Server] 未找到模块配置: ${moduleName}`);
    }
    const ModuleClass = registryConfig.moduleClass;
    const moduleInstance = new ModuleClass(registryConfig.moduleName, registryConfig.version);
    const moduleOptions = {
      store: { ...registryConfig.defaultStore },
      ...customConfig
    };
    await this.registerModuleWithRoutes(
      moduleInstance,
      moduleOptions,
      moduleName.charAt(0).toUpperCase() + moduleName.slice(1)
    );
    this[moduleName] = moduleInstance;
    this.logInfo(`模块注册完成: ${moduleName}`, {
      moduleName,
      shouldPreload,
      version: registryConfig.version
    });
    return { module: moduleInstance, config: registryConfig, shouldPreload };
  }
  /**
   * 注册指定的服务端模块
   * @param moduleConfigs 要注册的模块配置数组（模块名称或配置对象）
   */
  async registerModules(moduleConfigs) {
    console.log("[Server] 开始注册模块...");
    const configs = moduleConfigs || Object.keys(this.moduleRegistry);
    this.logInfo("开始批量注册模块", {
      moduleConfigs: configs,
      totalCount: configs.length
    });
    const registeredModules = [];
    for (const config of configs) {
      const configName = typeof config === "string" ? config : config.name;
      try {
        const result = await this.registerModuleByName(config);
        registeredModules.push(result);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError(`模块注册失败: ${configName}`, {
          moduleName: configName,
          error: errorMessage
        });
        console.error(`[Server] 模块注册失败:`, error);
        throw error;
      }
    }
    console.log("[Server] ✅ 所有模块注册完成");
    this.logInfo("所有模块注册完成", {
      registeredCount: registeredModules.length,
      moduleNames: registeredModules.map((m) => {
        var _a;
        return (_a = m == null ? void 0 : m.config) == null ? void 0 : _a.name;
      })
    });
    return registeredModules;
  }
  /**
   * 预加载指定模块的数据
   * @param registeredModules 已注册的模块信息
   */
  async preloadModulesData(registeredModules, options) {
    var _a, _b;
    console.log("[Server] 开始预加载模块数据...");
    const modulesToPreload = registeredModules.filter((m) => m.shouldPreload);
    this.logInfo("开始预加载模块数据", {
      totalModules: registeredModules.length,
      preloadCount: modulesToPreload.length,
      modulesToPreload
    });
    const preloadResults = [];
    for (const { module: module2, config, shouldPreload } of registeredModules) {
      if (!shouldPreload) {
        console.log(`[Server] ⏭️ 跳过 ${config.name} 模块预加载`);
        this.logInfo(`跳过模块预加载: ${config.name}`, { moduleName: config.name, reason: "shouldPreload=false" });
        continue;
      }
      if (typeof module2.preload === "function") {
        const startTime = Date.now();
        try {
          this.logInfo(`开始预加载模块: ${config.name}`, { moduleName: config.name });
          (_a = options == null ? void 0 : options.onModuleLoad) == null ? void 0 : _a.call(options, config.name);
          await module2.preload();
          (_b = options == null ? void 0 : options.onModuleLoadComplete) == null ? void 0 : _b.call(options, config.name);
          const duration = Date.now() - startTime;
          console.log(`[Server] ✅ ${config.name} 模块数据已预加载`);
          this.logInfo(`模块预加载成功: ${config.name}`, {
            moduleName: config.name,
            duration: `${duration}ms`
          });
          preloadResults.push({ name: config.name, success: true });
        } catch (error) {
          const duration = Date.now() - startTime;
          const errorMessage = error instanceof Error ? error.message : String(error);
          console.error(`[Server] ❌ ${config.name} 模块预加载失败:`, error);
          this.logError(`模块预加载失败: ${config.name}`, {
            moduleName: config.name,
            duration: `${duration}ms`,
            error: errorMessage
          });
          preloadResults.push({ name: config.name, success: false, error: errorMessage });
        }
      } else {
        console.log(`[Server] ⚠️ ${config.name} 模块未实现 preload() 方法`);
        this.logWarning(`模块未实现 preload 方法: ${config.name}`, { moduleName: config.name });
      }
    }
    const successCount = preloadResults.filter((r) => r.success).length;
    const failCount = preloadResults.filter((r) => !r.success).length;
    console.log("[Server] ✅ 所有模块数据预加载完成");
    this.logInfo("所有模块预加载完成", {
      successCount,
      failCount
    });
  }
  /**
   * 初始化 Server（注册模块并预加载数据）
   * @param moduleConfigs 要注册的模块配置
   * @param autoPreload 是否自动预加载数据
   */
  async initialize(moduleConfigs, autoPreload = true, options) {
    const startTime = Date.now();
    this.logInfo("Server 初始化开始", {
      moduleConfigCount: (moduleConfigs == null ? void 0 : moduleConfigs.length) ?? "all",
      autoPreload,
      moduleConfigs
    });
    this.registerServerRoutes();
    const registeredModules = await this.registerModules(moduleConfigs);
    if (autoPreload) {
      await this.preloadModulesData(registeredModules, options);
    } else {
      this.logInfo("跳过自动预加载", { autoPreload });
    }
    await this.setupProductsQuotationPriceBridge();
    this.core.effects.on(import_types2.ProductsHooks.onProductsSyncCompleted, (payload) => {
      this.recomputeAndNotifyProductQuery({
        changedIds: payload == null ? void 0 : payload.changedIds
      });
    });
    this.core.effects.on(import_types.FloorPlanHooks.onFloorPlansChanged, () => {
      void this.recomputeAndNotifyFloorPlanQuery();
    });
    this.core.effects.on(import_types3.OrderHooks.onOrdersChanged, () => {
      this.recomputeAndNotifyOrderQuery();
      this.recomputeAndNotifyBookingQuery();
      this.syncBookingRemoteCacheFromOrderChanges();
    });
    const duration = Date.now() - startTime;
    this.logInfo("Server 初始化完成", {
      duration: `${duration}ms`,
      registeredModuleCount: registeredModules.length
    });
    return registeredModules;
  }
  /**
   * 将普通层 QuotationModule 的报价单计算能力桥接到 Server Products 模块。
   */
  async setupProductsQuotationPriceBridge() {
    var _a;
    if (!this.products) {
      this.logWarning("setupProductsQuotationPriceBridge: Products 模块未注册");
      return;
    }
    if (!this.schedule) {
      this.logWarning("setupProductsQuotationPriceBridge: Schedule 模块未注册");
      return;
    }
    try {
      await this.schedule.loadAllSchedule();
      this.products.clearPriceCache();
      await this.products.setupQuotationPriceBridge({
        scheduleModule: this.schedule,
        channel: (_a = this.core.context) == null ? void 0 : _a.channel
      });
      this.logInfo("Products 报价单价格桥接初始化完成");
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.logError("Products 报价单价格桥接初始化失败", { error: errorMessage });
    }
  }
  /**
   * 获取 Products 模块实例
   */
  getProducts() {
    return this.products;
  }
  /**
   * 获取 Menu 模块实例
   */
  getMenu() {
    return this.menu;
  }
  /**
   * 获取 Quotation 模块实例
   */
  getQuotation() {
    return this.quotation;
  }
  /**
   * 获取 Schedule 模块实例
   */
  getSchedule() {
    return this.schedule;
  }
  /**
   * 获取所有已注册的模块列表
   */
  getRegisteredModules() {
    const modules = [];
    if (this.products)
      modules.push("products");
    if (this.menu)
      modules.push("menu");
    if (this.quotation)
      modules.push("quotation");
    if (this.schedule)
      modules.push("schedule");
    if (this.resource)
      modules.push("resource");
    if (this.order)
      modules.push("order");
    if (this.floor_plan)
      modules.push("floor_plan");
    return modules;
  }
  /**
   * 后台静默刷新商品数据
   * 重新拉取全量 SSE 接口，更新本地数据后触发 onProductsSyncCompleted
   * 不影响当前界面展示，适用于切回前台、定时刷新等场景
   */
  async refreshProductsInBackground() {
    if (!this.products) {
      this.logWarning("refreshProductsInBackground: Products 模块未注册");
      return;
    }
    this.logInfo("refreshProductsInBackground 开始");
    const startTime = Date.now();
    try {
      await this.products.silentRefresh();
      const duration = Date.now() - startTime;
      this.logInfo("refreshProductsInBackground 完成", { duration: `${duration}ms` });
    } catch (error) {
      const duration = Date.now() - startTime;
      const errorMessage = error instanceof Error ? error.message : String(error);
      console.error("[Server] refreshProductsInBackground 失败:", error);
      this.logError("refreshProductsInBackground 失败", {
        duration: `${duration}ms`,
        error: errorMessage
      });
    }
  }
  /**
   * 后台静默刷新订单数据
   * 重新拉取全量 SSE 接口，更新本地数据后触发 onOrdersSyncCompleted
   * 不影响当前界面展示，适用于切回前台、定时刷新等场景
   */
  async refreshOrdersInBackground() {
    if (!this.order) {
      this.logWarning("refreshOrdersInBackground: Order 模块未注册");
      return;
    }
    this.logInfo("refreshOrdersInBackground 开始");
    const startTime = Date.now();
    try {
      await this.order.silentRefresh();
      const duration = Date.now() - startTime;
      this.logInfo("refreshOrdersInBackground 完成", { duration: `${duration}ms` });
    } catch (error) {
      const duration = Date.now() - startTime;
      const errorMessage = error instanceof Error ? error.message : String(error);
      console.error("[Server] refreshOrdersInBackground 失败:", error);
      this.logError("refreshOrdersInBackground 失败", {
        duration: `${duration}ms`,
        error: errorMessage
      });
    }
  }
  /**
   * 清空所有server模块的IndexedDB缓存
   * @returns Promise<void>
   */
  async clearAllIndexDB() {
    console.log("[Server] 开始清空所有模块的IndexedDB缓存...");
    this.logInfo("开始清空所有模块的 IndexedDB 缓存");
    const clearTasks = [];
    const moduleNames = [];
    if (this.products) {
      clearTasks.push(this.products.clear());
      moduleNames.push("Products");
    }
    if (this.menu) {
      clearTasks.push(this.menu.clear());
      moduleNames.push("Menu");
    }
    if (this.quotation) {
      clearTasks.push(this.quotation.clear());
      moduleNames.push("Quotation");
    }
    if (this.schedule) {
      clearTasks.push(this.schedule.clear());
      moduleNames.push("Schedule");
    }
    if (this.resource) {
      clearTasks.push(this.resource.clear());
      moduleNames.push("Resource");
    }
    if (this.order) {
      clearTasks.push(this.order.clear());
      moduleNames.push("Order");
    }
    if (this.floor_plan) {
      clearTasks.push(this.floor_plan.clear());
      moduleNames.push("FloorPlan");
    }
    if (clearTasks.length === 0) {
      console.warn("[Server] 没有找到已注册的模块，无需清空");
      this.logWarning("没有找到已注册的模块，无需清空 IndexedDB");
      return;
    }
    this.logInfo("准备清空模块缓存", { moduleNames });
    try {
      await Promise.all(clearTasks);
      console.log(`[Server] ✅ 已成功清空所有模块的IndexedDB缓存: ${moduleNames.join(", ")}`);
      this.logInfo("成功清空所有模块的 IndexedDB 缓存", { moduleNames });
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      console.error("[Server] ❌ 清空IndexedDB缓存时发生错误:", error);
      this.logError("清空 IndexedDB 缓存时发生错误", { moduleNames, error: errorMessage });
      throw error;
    }
  }
  /**
   * 获取所有注册的路由
   */
  getRoutes() {
    return this.router;
  }
  /**
   * 根据方法和路径获取路由处理函数
   * @param method HTTP 方法
   * @param path 路径
   */
  getRouteHandler(method, path) {
    var _a;
    const exact = (_a = this.router[method]) == null ? void 0 : _a[path];
    if (exact) {
      return exact;
    }
    if (method === "get" && /^\/shop\/product\/query\/\d+$/.test(path)) {
      return this.handleProductQueryById;
    }
    if (method === "get" && this.prefixRouterGet.length > 0) {
      for (const { prefix, handler } of this.prefixRouterGet) {
        if (path === prefix || path.startsWith(`${prefix}/`)) {
          return handler;
        }
      }
    }
    return void 0;
  }
  /**
   * 检查路由是否存在
   * @param method HTTP 方法
   * @param path 路径
   */
  hasRoute(method, path) {
    return !!this.getRouteHandler(method, path);
  }
  /**
   * 执行路由处理函数
   * @param method HTTP 方法
   * @param path 路径
   * @param params 请求参数
   */
  async handleRoute(method, path, params) {
    const startTime = Date.now();
    this.logInfo(`路由请求开始: ${method.toUpperCase()} ${path}`, {
      method: method.toUpperCase(),
      path,
      url: params.url,
      data: params.data
    });
    const handler = this.getRouteHandler(method, path);
    if (!handler) {
      this.logError(`路由未找到: ${method.toUpperCase()} ${path}`, { method, path });
      throw new Error(`Route not found: ${method.toUpperCase()} ${path}`);
    }
    try {
      const result = await handler({ ...params, path });
      const duration = Date.now() - startTime;
      this.logInfo(`路由请求完成: ${method.toUpperCase()} ${path}`, {
        method: method.toUpperCase(),
        path,
        duration: `${duration}ms`,
        resultCode: result == null ? void 0 : result.code,
        resultStatus: result == null ? void 0 : result.status
      });
      return result;
    } catch (error) {
      const duration = Date.now() - startTime;
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.logError(`路由处理错误: ${method.toUpperCase()} ${path}`, {
        method: method.toUpperCase(),
        path,
        duration: `${duration}ms`,
        error: errorMessage,
        data: params.data
      });
      console.error(`[Server] 路由处理错误: ${method.toUpperCase()} ${path}`, error);
      throw error;
    }
  }
  /**
   * 获取所有路由列表（用于调试和文档）
   */
  getAllRoutes() {
    const routes = [];
    ["get", "post", "put", "remove"].forEach((method) => {
      Object.keys(this.router[method]).forEach((path) => {
        routes.push({ method, path });
      });
    });
    return routes;
  }
  /**
   * 注册 Server 层的业务路由
   * 这些路由需要编排多个模块的数据
   * @private
   */
  registerServerRoutes() {
    console.log("[Server] 注册 Server 层业务路由...");
    this.registerRoutes([
      {
        method: "post",
        path: "/shop/product/query",
        handler: this.handleProductQuery.bind(this)
      },
      {
        method: "post",
        path: "/shop/product/query/unsubscribe",
        handler: this.handleUnsubscribeProductQuery.bind(this)
      },
      {
        method: "post",
        path: "/shop/menu/schedule-time-points",
        handler: this.handleGetScheduleTimePoints.bind(this)
      },
      {
        method: "post",
        path: "/shop/order/v2/list",
        handler: this.handleOrderList.bind(this)
      },
      {
        method: "post",
        path: "/shop/order/v2/list/unsubscribe",
        handler: this.handleUnsubscribeOrderQuery.bind(this)
      },
      {
        method: "get",
        path: "/shop/schedule/booking",
        handler: this.handleBookingList.bind(this)
      },
      {
        method: "get",
        path: "/shop/schedule/booking/unsubscribe",
        handler: this.handleUnsubscribeBookingQuery.bind(this)
      },
      {
        method: "get",
        path: "/shop/form/resource/page",
        handler: this.handleResourceList.bind(this)
      },
      {
        method: "get",
        path: "/update/localOrder",
        handler: this.handleUpdateLocalOrder.bind(this)
      }
    ]);
    this.registerPrefixRoutes([
      {
        method: "get",
        prefix: "/shop/order/sales",
        handler: this.handleOrderSalesDetail.bind(this)
      },
      {
        method: "get",
        prefix: "/shop/schedule/floor-plan",
        handler: this.handleFloorPlanGet.bind(this)
      }
    ]);
  }
  /**
   * 根据 subscriberId 移除商品查询订阅者
   */
  removeProductQuerySubscriber(subscriberId) {
    if (subscriberId) {
      this.productQuerySubscribers.delete(subscriberId);
      this.logInfo("removeProductQuerySubscriber: 已移除订阅者", {
        subscriberId,
        remaining: this.productQuerySubscribers.size
      });
    }
  }
  /**
   * 从查询值中提取 YYYY-MM-DD 日期串。
   *
   * @example
   * this.extractQueryDate('2026-04-15 09:58:00') // => '2026-04-15'
   */
  extractQueryDate(raw) {
    if (raw == null)
      return null;
    const date = (0, import_dayjs.default)(raw);
    if (date.isValid()) {
      return date.format("YYYY-MM-DD");
    }
    const text = String(raw).trim();
    if (!text)
      return null;
    return text.split("T")[0].split(" ")[0] || null;
  }
  /**
   * 判断时间范围是否「开始和结束都不是今天」。
   *
   * @example
   * this.isRangeBothNotToday('2026-04-13', '2026-04-14') // => true
   */
  isRangeBothNotToday(startRaw, endRaw) {
    const startDate = this.extractQueryDate(startRaw);
    const endDate = this.extractQueryDate(endRaw);
    if (!startDate || !endDate)
      return false;
    const today = (0, import_dayjs.default)().format("YYYY-MM-DD");
    return startDate !== today && endDate !== today;
  }
  /**
   * 订单查询是否走本地：
   * - 当 start_time 与 end_time 都不是今天时，走远端；
   * - 其余情况走本地。
   */
  shouldUseLocalOrderQuery(data) {
    return !this.isRangeBothNotToday(data == null ? void 0 : data.start_time, data == null ? void 0 : data.end_time);
  }
  /**
   * 预约查询是否走本地：
   * - 当 sales_time_between 的开始和结束都不是今天时，走远端；
   * - 其余情况走本地。
   */
  shouldUseLocalBookingQuery(data) {
    const range = data == null ? void 0 : data.sales_time_between;
    if (!Array.isArray(range) || range.length < 2)
      return true;
    return !this.isRangeBothNotToday(range[0], range[1]);
  }
  /**
   * 日历 SSE 精简 with：由调用方显式声明 compact_fields 决定
   * - compact_fields === true → 精简字段（周/月视图）
   * - 其余（false / 未传）→ ['all']（日视图/表格/平面图合并）
   */
  resolveBookingSalesWith(queryPayload) {
    if ((queryPayload == null ? void 0 : queryPayload.compact_fields) === true) {
      return [
        "bookings:booking_id,start_date,start_time,end_date,end_time,holder,metadata,parent_id,item_type",
        "customer:id,display_name,phone",
        "products"
        // 'resources'
      ];
    }
    return ["all"];
  }
  /**
   * 日历 SSE 精简 select：渲染 + filterBookingsFromOrders 所需的主表字段
   * business_code / payment_status 不直接用于渲染，但 matchOrder 过滤依赖
   */
  resolveBookingSalesSelect() {
    return "status,payment_status,business_code,phone,customer_name,schedule_date,created_at,metadata";
  }
  normalizeBookingRemoteQueryPayload(data, withFields) {
    const isFullWith = withFields.length === 1 && withFields[0] === "all";
    const isCompact = (data == null ? void 0 : data.compact_fields) === true;
    return {
      ...data,
      form_record_ids: void 0,
      enable_remote_memory_cache: void 0,
      compact_fields: void 0,
      with: withFields,
      ...isFullWith ? {} : { select: this.resolveBookingSalesSelect() },
      ...isCompact ? { exclude_types: this.BOOKING_SALES_COMPACT_EXCLUDE_TYPES } : {},
      chunk_size: 50
    };
  }
  /**
   * 远端预约查询内存缓存开关：默认 false，仅显式 true 才启用。
   */
  isBookingRemoteMemoryCacheEnabled(queryPayload) {
    return (queryPayload == null ? void 0 : queryPayload.enable_remote_memory_cache) === true;
  }
  stableSerialize(value) {
    if (value === null || value === void 0)
      return "null";
    if (Array.isArray(value)) {
      return `[${value.map((item) => this.stableSerialize(item)).join(",")}]`;
    }
    if (typeof value === "object") {
      const obj = value;
      const keys = Object.keys(obj).filter((k) => obj[k] !== void 0).sort();
      return `{${keys.map((k) => `${JSON.stringify(k)}:${this.stableSerialize(obj[k])}`).join(",")}}`;
    }
    return JSON.stringify(value);
  }
  buildBookingRemoteCacheKey(payload) {
    return this.stableSerialize(payload);
  }
  parseBookingSalesRangeMeta(payload) {
    const range = payload == null ? void 0 : payload.sales_time_between;
    if (!Array.isArray(range) || range.length < 2)
      return null;
    const startAtMs = (0, import_dayjs.default)(range[0]).valueOf();
    const endAtMs = (0, import_dayjs.default)(range[1]).valueOf();
    if (!Number.isFinite(startAtMs) || !Number.isFinite(endAtMs))
      return null;
    if (endAtMs <= startAtMs)
      return null;
    return { startAtMs, endAtMs };
  }
  readBookingRemoteCache(cacheKey) {
    const entry = this.bookingRemoteCache.get(cacheKey);
    if (!entry)
      return null;
    if (entry.stale) {
      this.bookingRemoteCache.delete(cacheKey);
      return null;
    }
    const now = Date.now();
    if (now - entry.updatedAt > this.BOOKING_REMOTE_CACHE_TTL_MS) {
      this.bookingRemoteCache.delete(cacheKey);
      return null;
    }
    return entry;
  }
  writeBookingRemoteCache(entry) {
    this.bookingRemoteCache.set(entry.key, entry);
    if (this.bookingRemoteCache.size <= this.BOOKING_REMOTE_CACHE_MAX_ENTRIES) {
      return;
    }
    let oldestKey = null;
    let oldestTime = Number.POSITIVE_INFINITY;
    for (const [key, cache] of this.bookingRemoteCache.entries()) {
      if (cache.updatedAt < oldestTime) {
        oldestTime = cache.updatedAt;
        oldestKey = key;
      }
    }
    if (oldestKey)
      this.bookingRemoteCache.delete(oldestKey);
  }
  toOrderIdKey(order) {
    if (!order || typeof order !== "object")
      return null;
    const raw = order.order_id;
    if (raw === void 0 || raw === null || raw === "")
      return null;
    return String(raw);
  }
  markBookingRemoteCacheAllStale(reason) {
    if (this.bookingRemoteCache.size === 0)
      return;
    for (const entry of this.bookingRemoteCache.values()) {
      entry.stale = true;
    }
    this.logWarning("bookingRemoteCache: 全量标记失效", {
      reason,
      cacheSize: this.bookingRemoteCache.size
    });
  }
  buildBookingResponse(bookingResult, extra) {
    return {
      code: 200,
      data: {
        ...extra ?? {},
        list: bookingResult.list || [],
        count: bookingResult.count || 0,
        size: bookingResult.size || 0,
        skip: bookingResult.skip || 0
      },
      message: "",
      status: true
    };
  }
  notifyBookingRemoteSubscribersByCacheKey(cacheKey, entry, reason) {
    if (this.bookingRemoteQuerySubscribers.size === 0)
      return;
    for (const [subscriberId, subscriber] of this.bookingRemoteQuerySubscribers.entries()) {
      if (subscriber.cacheKey !== cacheKey)
        continue;
      try {
        const callbackStartAt = Date.now();
        subscriber.callback(
          this.buildBookingResponse(entry.bookingResult, {
            cache_hit: true,
            from_cache_sync: true,
            sync_reason: reason
          })
        );
        const callbackEndAt = Date.now();
        this.logInfo("notifyBookingRemoteSubscribersByCacheKey: 已推送", {
          subscriberId,
          cacheKey,
          reason,
          callbackDurationMs: callbackEndAt - callbackStartAt
        });
      } catch (error) {
        const errMsg = error instanceof Error ? error.message : String(error);
        this.logError("notifyBookingRemoteSubscribersByCacheKey: 推送失败", {
          subscriberId,
          cacheKey,
          reason,
          error: errMsg
        });
      }
    }
  }
  syncBookingRemoteCacheFromOrderChanges() {
    var _a, _b;
    if (this.bookingRemoteCache.size === 0)
      return;
    const syncStartAt = Date.now();
    const latestOrders = ((_b = (_a = this.order) == null ? void 0 : _a.getOrders) == null ? void 0 : _b.call(_a)) ?? [];
    if (!Array.isArray(latestOrders) || latestOrders.length === 0) {
      this.markBookingRemoteCacheAllStale("orderStoreEmptyAfterChange");
      return;
    }
    let syncedEntryCount = 0;
    for (const [cacheKey, entry] of this.bookingRemoteCache.entries()) {
      if (entry.stale) {
        this.bookingRemoteCache.delete(cacheKey);
        continue;
      }
      try {
        const queryPayload = entry.queryPayload;
        const orderMap = /* @__PURE__ */ new Map();
        for (const order of entry.rawOrders) {
          const key = this.toOrderIdKey(order);
          if (key)
            orderMap.set(key, order);
        }
        let changed = false;
        for (const latest of latestOrders) {
          const key = this.toOrderIdKey(latest);
          if (!key)
            continue;
          if (orderMap.has(key)) {
            orderMap.set(key, latest);
            changed = true;
            continue;
          }
          orderMap.set(key, latest);
          changed = true;
        }
        if (!changed)
          continue;
        const mergedOrders = [...orderMap.values()];
        const filterStartAt = Date.now();
        const bookingResult = (0, import_filterBookings.sortBookings)(
          (0, import_filterBookings.filterBookingsFromOrders)(mergedOrders, queryPayload),
          queryPayload
        );
        const filterEndAt = Date.now();
        const nextEntry = {
          ...entry,
          rawOrders: mergedOrders,
          bookingResult,
          updatedAt: Date.now(),
          stale: false
        };
        this.writeBookingRemoteCache(nextEntry);
        this.notifyBookingRemoteSubscribersByCacheKey(
          cacheKey,
          nextEntry,
          "orders_changed"
        );
        syncedEntryCount += 1;
        this.logInfo("bookingRemoteCache: 单条缓存同步完成", {
          cacheKey,
          mergedOrderCount: mergedOrders.length,
          filteredBookingCount: bookingResult.count,
          filterDurationMs: filterEndAt - filterStartAt
        });
      } catch (error) {
        const errMsg = error instanceof Error ? error.message : String(error);
        this.logWarning("bookingRemoteCache: 同步失败并标记失效", {
          cacheKey,
          error: errMsg
        });
        const current = this.bookingRemoteCache.get(cacheKey);
        if (current)
          current.stale = true;
      }
    }
    const syncEndAt = Date.now();
    if (syncedEntryCount > 0) {
      this.logInfo("bookingRemoteCache: 已同步 Ably 变更", {
        syncedEntryCount,
        cacheSize: this.bookingRemoteCache.size,
        totalSyncDurationMs: syncEndAt - syncStartAt
      });
    }
  }
  /**
   * 非本地窗口的订单查询：走真实 API。
   */
  async fetchOrderListFromAPI(data) {
    var _a;
    if (!((_a = this.app) == null ? void 0 : _a.request)) {
      this.logError("fetchOrderListFromAPI: app.request 不可用");
      return {
        code: 500,
        message: "app.request 不可用",
        data: { list: [], count: 0 },
        status: false
      };
    }
    try {
      const response = await this.app.request.post("/shop/order/v2/list", data, {
        isShopApi: true
      });
      const payload = (response == null ? void 0 : response.data) ?? response;
      const list = Array.isArray(payload == null ? void 0 : payload.list) ? payload.list : [];
      const count = typeof (payload == null ? void 0 : payload.count) === "number" ? payload.count : list.length;
      return {
        code: 200,
        data: { ...payload, list, count },
        message: "",
        status: true
      };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.logError("fetchOrderListFromAPI: 请求失败", { error: errorMessage });
      return {
        code: 500,
        message: errorMessage,
        data: { list: [], count: 0 },
        status: false
      };
    }
  }
  /**
   * 非今天的预约查询：通过 SSE 流式拉取订单，再做本地 booking 筛选展开
   */
  async fetchBookingListFromAPI(data) {
    var _a;
    if (!this.order) {
      this.logError("fetchBookingListFromAPI: Order 模块不可用");
      return {
        code: 500,
        message: "Order 模块不可用",
        data: { list: [], count: 0 },
        status: false
      };
    }
    try {
      const memoryCacheEnabled = this.isBookingRemoteMemoryCacheEnabled(data);
      const withFields = this.resolveBookingSalesWith(data);
      const requestPayload = this.normalizeBookingRemoteQueryPayload(
        data,
        withFields
      );
      const cacheKey = this.buildBookingRemoteCacheKey(requestPayload);
      if (memoryCacheEnabled) {
        const cached = this.readBookingRemoteCache(cacheKey);
        if (cached) {
          this.logInfo("fetchBookingListFromAPI: 命中内存缓存", {
            cacheKey,
            listCount: cached.bookingResult.count,
            withFields: cached.withFields
          });
          return this.buildBookingResponse(cached.bookingResult, {
            cache_hit: true
          });
        }
      }
      const rawList = await this.order.fetchOrdersBySSE(requestPayload);
      const bookingResult = (0, import_filterBookings.sortBookings)(
        (0, import_filterBookings.filterBookingsFromOrders)(rawList, data),
        data
      );
      if (typeof globalThis !== "undefined") {
        globalThis.__SSE_BOOKING_DEBUG__ = {
          ts: (/* @__PURE__ */ new Date()).toISOString(),
          sseRequestPayload: requestPayload,
          calendarFilters: data,
          rawOrderCount: rawList.length,
          rawOrderSample: rawList.slice(0, 2).map((o) => {
            var _a2, _b, _c;
            return {
              order_id: o == null ? void 0 : o.order_id,
              business_code: o == null ? void 0 : o.business_code,
              status: o == null ? void 0 : o.status,
              payment_status: o == null ? void 0 : o.payment_status,
              bookingsCount: (_a2 = o == null ? void 0 : o.bookings) == null ? void 0 : _a2.length,
              firstBooking: ((_b = o == null ? void 0 : o.bookings) == null ? void 0 : _b[0]) ? {
                start_date: o.bookings[0].start_date,
                start_time: o.bookings[0].start_time,
                parent_id: o.bookings[0].parent_id,
                item_type: o.bookings[0].item_type,
                resourcesCount: (_c = o.bookings[0].resources) == null ? void 0 : _c.length
              } : null
            };
          }),
          filteredBookingCount: bookingResult.count,
          filteredListLength: (_a = bookingResult.list) == null ? void 0 : _a.length
        };
      }
      if (memoryCacheEnabled) {
        this.writeBookingRemoteCache({
          key: cacheKey,
          queryPayload: data,
          withFields,
          rawOrders: Array.isArray(rawList) ? rawList : [],
          bookingResult,
          updatedAt: Date.now(),
          stale: false,
          rangeMeta: this.parseBookingSalesRangeMeta(requestPayload)
        });
      }
      this.logInfo("fetchBookingListFromAPI: SSE 返回并拆分完成", {
        rawCount: rawList.length,
        flattenedCount: bookingResult.count,
        cacheKey,
        withFields
      });
      return this.buildBookingResponse(bookingResult);
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.logError("fetchBookingListFromAPI: SSE 请求失败", { error: errorMessage });
      return {
        code: 500,
        message: errorMessage,
        data: { list: [], count: 0 },
        status: false
      };
    }
  }
  /**
   * 解析 order_ids 入参，兼容 url query / data 字段、字符串(csv) / 数组两种形态。
   * 自动 trim、去空、按字符串去重，输出归一化后的字符串数组。
   *
   * @example
   * // url: /update/localOrder?order_ids=1,2,2,, → ['1','2']
   * this.parseOrderIdsParam(url, undefined)
   *
   * @example
   * // data: { order_ids: [1, '2', null] } → ['1','2']
   * this.parseOrderIdsParam('', { order_ids: [1, '2', null] })
   */
  parseOrderIdsParam(url, data) {
    const collected = [];
    const pushRaw = (raw) => {
      if (raw === void 0 || raw === null)
        return;
      if (Array.isArray(raw)) {
        raw.forEach(pushRaw);
        return;
      }
      const str = String(raw).trim();
      if (!str)
        return;
      str.split(",").forEach((piece) => {
        const v = piece.trim();
        if (v)
          collected.push(v);
      });
    };
    if (data && typeof data === "object") {
      pushRaw(data.order_ids);
    }
    pushRaw(this.extractQueryParam(url, "order_ids"));
    const seen = /* @__PURE__ */ new Set();
    const result = [];
    for (const id of collected) {
      if (seen.has(id))
        continue;
      seen.add(id);
      result.push(id);
    }
    return result;
  }
  /**
   * 批量代理刷新 / 合并订单到本地：并发拉详情 → 单次合并 → 单次 emit。
   * - 单笔失败不影响其他成功项
   * - 没有任何成功项时不触发 emit / 落库
   *
   * @example
   * await this.handleUpdateLocalOrdersBatch(['96971', '96972'])
   */
  async handleUpdateLocalOrdersBatch(orderIds) {
    var _a;
    this.logInfo("handleUpdateLocalOrdersBatch: 开始处理", {
      count: orderIds.length,
      orderIds
    });
    if (!this.order) {
      this.logError("handleUpdateLocalOrdersBatch: Order 模块未注册");
      return { code: 500, status: false, message: "Order 模块未注册", data: null };
    }
    if (!((_a = this.app) == null ? void 0 : _a.request)) {
      this.logError("handleUpdateLocalOrdersBatch: app.request 不可用");
      return { code: 500, status: false, message: "app.request 不可用", data: null };
    }
    const existedBefore = /* @__PURE__ */ new Map();
    for (const id of orderIds) {
      existedBefore.set(id, !!this.order.getOrderByOrderId(id));
    }
    let fetched = [];
    try {
      fetched = await this.order.fetchOrdersByHttp(orderIds);
    } catch (error) {
      const message = error instanceof Error ? error.message : String(error);
      this.logError("handleUpdateLocalOrdersBatch: 批量拉取失败", { message });
      return { code: 500, status: false, message, data: null };
    }
    const fetchedMap = /* @__PURE__ */ new Map();
    for (const order of fetched) {
      const oid = order == null ? void 0 : order.order_id;
      if (oid === void 0 || oid === null)
        continue;
      fetchedMap.set(String(oid), order);
    }
    const freshOrders = [];
    const succeedIds = [];
    const failed = [];
    for (const id of orderIds) {
      const fresh = fetchedMap.get(id);
      if (fresh) {
        freshOrders.push(fresh);
        succeedIds.push(id);
      } else {
        failed.push({ order_id: id, message: "后端未返回该订单详情" });
      }
    }
    if (freshOrders.length > 0) {
      try {
        await this.order.upsertOrdersFromRemote(freshOrders);
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        this.logError("handleUpdateLocalOrdersBatch: 合并写入失败", { message });
        return { code: 500, status: false, message, data: null };
      }
    }
    const overwritten = succeedIds.filter((id) => existedBefore.get(id));
    const inserted = succeedIds.filter((id) => !existedBefore.get(id));
    this.logInfo("handleUpdateLocalOrdersBatch: 完成", {
      total: orderIds.length,
      overwrittenCount: overwritten.length,
      insertedCount: inserted.length,
      failedCount: failed.length
    });
    return {
      code: 200,
      status: true,
      message: "",
      data: { overwritten, inserted, failed }
    };
  }
  /**
   * 从 url 中解析指定 query 参数，兼容相对路径与绝对路径
   */
  extractQueryParam(url, key) {
    if (!url)
      return null;
    try {
      const target = url.startsWith("http") ? new URL(url) : new URL(url, "http://placeholder.local");
      const value = target.searchParams.get(key);
      return value ?? null;
    } catch {
      const queryIndex = url.indexOf("?");
      if (queryIndex < 0)
        return null;
      const query = url.slice(queryIndex + 1);
      for (const pair of query.split("&")) {
        if (!pair)
          continue;
        const [rawKey, rawValue = ""] = pair.split("=");
        try {
          if (decodeURIComponent(rawKey) === key) {
            return decodeURIComponent(rawValue);
          }
        } catch {
          if (rawKey === key)
            return rawValue;
        }
      }
      return null;
    }
  }
  extractOrderSalesDetailId(url) {
    const path = this.parseRequestPath(url);
    const match = path.match(/^\/shop\/order\/sales\/([^/?#]+)$/);
    return (match == null ? void 0 : match[1]) ? decodeURIComponent(match[1]) : null;
  }
  buildOrderSalesDetailBackendPath(orderId, data) {
    const rawWith = data && typeof data === "object" ? data.with : void 0;
    const withFields = Array.isArray(rawWith) && rawWith.length > 0 ? rawWith : ["products", "scheduleEvents"];
    const searchParams = new URLSearchParams();
    withFields.forEach((field) => {
      if (field === void 0 || field === null || field === "")
        return;
      searchParams.append("with[]", String(field));
    });
    searchParams.append("lookup_mode", "multi");
    const query = searchParams.toString();
    return `/shop/order/sales/${encodeURIComponent(orderId)}${query ? `?${query}` : ""}`;
  }
  /**
   * 从 url 或路由 path 解析 pathname（不含 query，去掉末尾 /）
   */
  parseRequestPath(url, routePath) {
    const raw = routePath || url;
    const noQuery = raw.split("?")[0] || "";
    try {
      const pathname = url.startsWith("http") ? new URL(url).pathname : noQuery;
      return pathname.replace(/\/$/, "") || pathname;
    } catch {
      return noQuery.replace(/\/$/, "");
    }
  }
  /**
   * 解析平面图 GET 路径为查询上下文
   */
  resolveFloorPlanQueryContext(path, base) {
    if (path === base) {
      return { kind: "list" };
    }
    if (!path.startsWith(`${base}/`)) {
      return null;
    }
    const after = path.slice(base.length + 1);
    if (after === "unsubscribe") {
      return null;
    }
    if (after.startsWith("code/")) {
      const code = decodeURIComponent(after.slice("code/".length));
      if (!code)
        return null;
      return { kind: "code", code };
    }
    if (/^\d+$/.test(after)) {
      return { kind: "id", id: after };
    }
    return null;
  }
  computeFloorPlanQueryResult(context) {
    if (!this.floor_plan) {
      return {
        status: false,
        code: 500,
        message: "Floor plan 模块未注册",
        data: null
      };
    }
    if (context.kind === "list") {
      return {
        status: true,
        code: 200,
        message: "",
        data: this.floor_plan.getSortedList()
      };
    }
    if (context.kind === "id") {
      const item2 = this.floor_plan.getById(context.id);
      if (!item2) {
        return { status: false, code: 404, message: "Not Found", data: null };
      }
      return { status: true, code: 200, message: "", data: item2 };
    }
    const item = this.floor_plan.getByCode(context.code);
    if (!item) {
      return { status: false, code: 404, message: "Not Found", data: null };
    }
    return { status: true, code: 200, message: "", data: item };
  }
  /**
   * 平面图数据变更后向所有 GET 订阅者推送最新结果
   */
  async recomputeAndNotifyFloorPlanQuery() {
    if (this.floorPlanQuerySubscribers.size === 0)
      return;
    this.logInfo("recomputeAndNotifyFloorPlanQuery: 开始推送", {
      subscriberCount: this.floorPlanQuerySubscribers.size
    });
    for (const [subscriberId, sub] of this.floorPlanQuerySubscribers.entries()) {
      try {
        const result = this.computeFloorPlanQueryResult(sub.context);
        sub.callback(result);
        this.logInfo("recomputeAndNotifyFloorPlanQuery: 已推送", { subscriberId });
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError("recomputeAndNotifyFloorPlanQuery: 推送失败", {
          subscriberId,
          error: errorMessage
        });
      }
    }
  }
  /**
   * 取消平面图 GET 订阅（也可走 GET .../unsubscribe + subscriberId）
   */
  removeFloorPlanQuerySubscriber(subscriberId) {
    if (subscriberId) {
      this.floorPlanQuerySubscribers.delete(subscriberId);
      this.logInfo("removeFloorPlanQuerySubscriber: 已移除", {
        subscriberId,
        remaining: this.floorPlanQuerySubscribers.size
      });
    }
  }
  /**
   * 订单列表本地计算（编排 Order 模块）
   * filter 逻辑暂为 mock，仅记录参数
   */
  async computeOrderQueryResult(data) {
    this.logInfo("computeOrderQueryResult: 开始过滤", { data });
    console.log("[Server] computeOrderQueryResult", data);
    if (!this.order) {
      this.logError("computeOrderQueryResult: Order 模块未注册");
      return {
        code: 500,
        message: "Order 模块未注册",
        data: { list: [], count: 0 },
        status: false
      };
    }
    const rawList = this.order.getOrders();
    this.logInfo("computeOrderQueryResult: 本地订单数量", { rawCount: rawList.length });
    const result = (0, import_filterOrders.filterOrders)(rawList, data);
    this.logInfo("computeOrderQueryResult: 过滤结果", {
      rawCount: rawList.length,
      filteredCount: result.count,
      size: result.size,
      skip: result.skip,
      rejected: result.rejected
    });
    return {
      code: 200,
      data: result,
      message: "",
      status: true
    };
  }
  /**
   * 预约列表本地计算（编排 Order 模块）
   * 从订单中展开 bookings，再按条件筛选 + 分页
   */
  async computeBookingQueryResult(data) {
    if (!this.order) {
      this.logError("computeBookingQueryResult: Order 模块未注册");
      return {
        code: 500,
        message: "Order 模块未注册",
        data: { list: [], count: 0 },
        status: false
      };
    }
    const rawOrders = this.order.getOrders();
    let result = (0, import_filterBookings.filterBookingsFromOrders)(rawOrders, data);
    result = (0, import_filterBookings.sortBookings)(result, data);
    this.logInfo("computeBookingQueryResult: 过滤结果", {
      orderCount: rawOrders.length,
      filteredCount: result.count,
      size: result.size,
      skip: result.skip
    });
    return {
      code: 200,
      data: result,
      message: "",
      status: true
    };
  }
  /**
   * 商品查询的核心计算逻辑（编排 Products、Menu、Schedule 模块）
   * 供 handleProductQuery 首次返回及 pubsub 变更推送复用
   * @param context 查询上下文
   * @param options 可选参数
   * @param options.changedIds 变更的商品 IDs，用于增量更新价格缓存
   */
  async computeProductQueryResult(context, options) {
    const tTotal = performance.now();
    const { menu_list_ids, schedule_date, schedule_datetime, customer_id, product_id } = context;
    this.logInfo("computeProductQueryResult 开始", {
      menuListIdsCount: (menu_list_ids == null ? void 0 : menu_list_ids.length) ?? 0,
      schedule_datetime,
      schedule_date,
      customer_id,
      product_id,
      changedIds: options == null ? void 0 : options.changedIds
    });
    if (!this.products) {
      this.logError("computeProductQueryResult: Products 模块未注册");
      return { message: "Products 模块未注册", data: { list: [], count: 0 } };
    }
    if (product_id != null && Number.isFinite(Number(product_id))) {
      const pid = Number(product_id);
      const tPrice2 = performance.now();
      const allProductsWithPrice = await this.products.getProductsWithPrice(schedule_date, {
        scheduleModule: this.getSchedule()
      }, {
        changedIds: options == null ? void 0 : options.changedIds
      });
      (0, import_product.perfMark)("computeQuery.getProductsWithPrice(single)", performance.now() - tPrice2, {
        count: allProductsWithPrice.length,
        productId: pid
      });
      const published = allProductsWithPrice.filter((p) => ((p == null ? void 0 : p.status) || "published") === "published");
      const item = published.find((p) => Number(p.id) === pid) ?? null;
      (0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
        mode: "single",
        productId: pid,
        found: !!item
      });
      this.logInfo("computeProductQueryResult 完成（单商品）", {
        productId: pid,
        found: !!item
      });
      return {
        code: 200,
        data: item,
        message: item ? "" : "商品不存在或未发布",
        status: true
      };
    }
    if (!this.menu) {
      this.logError("computeProductQueryResult: Menu 模块未注册");
      return { message: "Menu 模块未注册", data: { list: [], count: 0 } };
    }
    if (!this.schedule) {
      this.logError("computeProductQueryResult: Schedule 模块未注册");
      return { message: "Schedule 模块未注册", data: { list: [], count: 0 } };
    }
    let activeMenuList = [];
    if (menu_list_ids && Array.isArray(menu_list_ids) && menu_list_ids.length > 0) {
      const tMenu = performance.now();
      const menuList = this.menu.getMenuByIds(menu_list_ids);
      activeMenuList = menuList.filter((menu) => {
        var _a;
        return ((_a = this.schedule) == null ? void 0 : _a.getDateIsInSchedule(schedule_datetime, menu.schedule)) || false;
      });
      (0, import_product.perfMark)("computeQuery.filterActiveMenu", performance.now() - tMenu, {
        totalMenu: menuList.length,
        activeMenu: activeMenuList.length
      });
    }
    const tFilter = performance.now();
    const productScope = this.getProductScopeByMenuConfig(activeMenuList);
    const scopedProductIds = this.products.getProductIdsByScope(productScope);
    (0, import_product.perfMark)("computeQuery.filterByMenu", performance.now() - tFilter, {
      scopedProductCount: scopedProductIds.length,
      activeMenuCount: activeMenuList.length,
      isAllProducts: !!productScope.isAllProducts
    });
    const tPrice = performance.now();
    let filteredProducts = scopedProductIds.length > 0 ? await this.products.getProductsWithPrice(schedule_date, {
      scheduleModule: this.getSchedule(),
      schedule_datetime,
      customer_id
    }, {
      changedIds: options == null ? void 0 : options.changedIds,
      productIds: productScope.isAllProducts ? void 0 : scopedProductIds
    }) : [];
    (0, import_product.perfMark)("computeQuery.getProductsWithPrice", performance.now() - tPrice, {
      count: filteredProducts.length,
      scopedProductCount: scopedProductIds.length
    });
    const tStatus = performance.now();
    const beforeStatusCount = filteredProducts.length;
    filteredProducts = filteredProducts.filter((p) => ((p == null ? void 0 : p.status) || "published") === "published");
    (0, import_product.perfMark)("computeQuery.filterByStatus", performance.now() - tStatus, {
      before: beforeStatusCount,
      after: filteredProducts.length
    });
    const tSort = performance.now();
    filteredProducts = filteredProducts.sort((a, b) => {
      const sortDiff = Number(b.sort) - Number(a.sort);
      if (sortDiff !== 0)
        return sortDiff;
      return (a.title || "").localeCompare(b.title || "");
    });
    (0, import_product.perfMark)("computeQuery.sort", performance.now() - tSort, { count: filteredProducts.length });
    (0, import_product.perfMark)("computeProductQueryResult", performance.now() - tTotal, {
      scopedProductCount: scopedProductIds.length,
      filteredCount: filteredProducts.length,
      activeMenuCount: activeMenuList.length
    });
    this.logInfo("computeProductQueryResult 完成", {
      scopedProductCount: scopedProductIds.length,
      filteredCount: filteredProducts.length,
      activeMenuCount: activeMenuList.length
    });
    return {
      code: 200,
      data: { list: filteredProducts, count: filteredProducts.length },
      message: "",
      status: true
    };
  }
  /**
   * 数据变更后，遍历所有订阅者重新计算查询结果并通过 callback 推送
   * 由 ProductsModule 的 onProductsSyncCompleted 事件触发
   * @param options 可选参数
   * @param options.changedIds 变更的商品 IDs，用于增量更新价格缓存
   */
  async recomputeAndNotifyProductQuery(options) {
    if (this.productQuerySubscribers.size === 0)
      return;
    this.logInfo("recomputeAndNotifyProductQuery: 开始推送", {
      subscriberCount: this.productQuerySubscribers.size,
      changedIds: options == null ? void 0 : options.changedIds
    });
    for (const [subscriberId, subscriber] of this.productQuerySubscribers.entries()) {
      try {
        const result = await this.computeProductQueryResult(subscriber.context, {
          changedIds: options == null ? void 0 : options.changedIds
        });
        subscriber.callback(result);
        this.logInfo("recomputeAndNotifyProductQuery: 已推送", { subscriberId });
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError("recomputeAndNotifyProductQuery: 推送失败", {
          subscriberId,
          error: errorMessage
        });
      }
    }
  }
  /**
   * 订单数据变更后，遍历订阅者重新计算并通过 callback 推送
   */
  async recomputeAndNotifyOrderQuery() {
    if (this.orderQuerySubscribers.size === 0)
      return;
    const notifyStartAt = Date.now();
    this.logInfo("recomputeAndNotifyOrderQuery: 开始推送", {
      subscriberCount: this.orderQuerySubscribers.size,
      notifyStartAt: new Date(notifyStartAt).toISOString()
    });
    for (const [subscriberId, subscriber] of this.orderQuerySubscribers.entries()) {
      try {
        const computeStartAt = Date.now();
        const result = await this.computeOrderQueryResult(subscriber.context);
        const computeEndAt = Date.now();
        const callbackStartAt = Date.now();
        subscriber.callback(result);
        const callbackEndAt = Date.now();
        this.logInfo("recomputeAndNotifyOrderQuery: 已推送", {
          subscriberId,
          computeDurationMs: computeEndAt - computeStartAt,
          callbackDurationMs: callbackEndAt - callbackStartAt,
          totalDurationMs: callbackEndAt - computeStartAt
        });
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError("recomputeAndNotifyOrderQuery: 推送失败", {
          subscriberId,
          error: errorMessage
        });
      }
    }
    const notifyEndAt = Date.now();
    this.logInfo("recomputeAndNotifyOrderQuery: 推送完成", {
      subscriberCount: this.orderQuerySubscribers.size,
      totalNotifyDurationMs: notifyEndAt - notifyStartAt
    });
  }
  /**
   * 预约数据变更后，遍历订阅者重新计算并通过 callback 推送
   */
  async recomputeAndNotifyBookingQuery() {
    if (this.bookingQuerySubscribers.size === 0)
      return;
    this.logInfo("recomputeAndNotifyBookingQuery: 开始推送", {
      subscriberCount: this.bookingQuerySubscribers.size
    });
    for (const [subscriberId, subscriber] of this.bookingQuerySubscribers.entries()) {
      try {
        const result = await this.computeBookingQueryResult(subscriber.context);
        subscriber.callback(result);
        this.logInfo("recomputeAndNotifyBookingQuery: 已推送", { subscriberId });
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logError("recomputeAndNotifyBookingQuery: 推送失败", {
          subscriberId,
          error: errorMessage
        });
      }
    }
  }
  /**
   * 根据餐牌配置提取轻量商品范围。
   * @private
   */
  getProductScopeByMenuConfig(activeMenuList) {
    if (!activeMenuList || activeMenuList.length === 0) {
      console.log("[Server] 没有生效的餐牌，返回空数组");
      this.logInfo("getProductScopeByMenuConfig: 没有生效的餐牌，返回空数组", {
        activeMenuCount: 0
      });
      return { productIds: [], collectionIds: [] };
    }
    const allowedProductIds = /* @__PURE__ */ new Set();
    const allowedCollectionIds = /* @__PURE__ */ new Set();
    let hasProductAll = false;
    for (const menu of activeMenuList) {
      const config = menu.partyroom_package;
      if (!config) {
        console.warn("[Server] 餐牌缺少 partyroom_package 配置:", menu);
        this.logWarning("getProductScopeByMenuConfig: 餐牌缺少 partyroom_package 配置", {
          menuId: menu.form_record_id,
          menuName: menu.name
        });
        continue;
      }
      if (config.type === "product_all") {
        console.log("[Server] 餐牌允许所有商品:", menu.name);
        this.logInfo("getProductScopeByMenuConfig: 餐牌允许所有商品", {
          menuId: menu.form_record_id,
          menuName: menu.name,
          configType: config.type
        });
        hasProductAll = true;
        break;
      }
      if (config.type === "products" && Array.isArray(config.products)) {
        const productIds = config.products.map((item) => item.product_id);
        productIds.forEach((id) => id && allowedProductIds.add(id));
        console.log("[Server] 餐牌允许指定商品 (product_ids):", menu.name, productIds);
        this.logInfo("getProductScopeByMenuConfig: 餐牌允许指定商品", {
          menuId: menu.form_record_id,
          menuName: menu.name,
          configType: config.type,
          productIdsCount: productIds.length
        });
      }
      if (config.type === "product_collection" && Array.isArray(config.products)) {
        const collectionIds = config.products.map((item) => item.product_collection_id);
        collectionIds.forEach((id) => id && allowedCollectionIds.add(id));
        console.log("[Server] 餐牌允许商品集合 (product_collection):", menu.name, collectionIds);
        this.logInfo("getProductScopeByMenuConfig: 餐牌允许商品集合", {
          menuId: menu.form_record_id,
          menuName: menu.name,
          configType: config.type,
          collectionIdsCount: collectionIds.length
        });
      }
    }
    if (hasProductAll) {
      this.logInfo("getProductScopeByMenuConfig: 返回所有商品 scope（product_all）");
      return { isAllProducts: true };
    }
    if (allowedProductIds.size === 0 && allowedCollectionIds.size === 0) {
      console.log("[Server] 没有允许的商品和集合");
      this.logWarning("getProductScopeByMenuConfig: 没有允许的商品和集合", {
        activeMenuCount: activeMenuList.length
      });
      return { productIds: [], collectionIds: [] };
    }
    const allowedProductIdsArray = Array.from(allowedProductIds);
    const allowedCollectionIdsArray = Array.from(allowedCollectionIds);
    console.log("[Server] 允许的商品 IDs:", allowedProductIdsArray);
    console.log("[Server] 允许的集合 IDs:", allowedCollectionIdsArray);
    this.logInfo("getProductScopeByMenuConfig: 收集到的允许规则", {
      allowedProductCount: allowedProductIds.size,
      allowedCollectionCount: allowedCollectionIds.size
    });
    return {
      productIds: allowedProductIdsArray,
      collectionIds: allowedCollectionIdsArray
    };
  }
  /**
   * 记录信息日志
   * @param title 日志标题
   * @param metadata 日志元数据
   */
  logInfo(title, metadata) {
    try {
      if (this.logger) {
        this.logger.addLog({
          type: "info",
          title: `[Server] ${title}`,
          metadata: metadata || {}
        });
      }
    } catch {
    }
  }
  /**
   * 记录警告日志
   * @param title 日志标题
   * @param metadata 日志元数据
   */
  logWarning(title, metadata) {
    try {
      if (this.logger) {
        this.logger.addLog({
          type: "warning",
          title: `[Server] ${title}`,
          metadata: metadata || {}
        });
      }
    } catch {
    }
  }
  /**
   * 记录错误日志
   * @param title 日志标题
   * @param metadata 日志元数据
   */
  logError(title, metadata) {
    try {
      if (this.logger) {
        this.logger.addLog({
          type: "error",
          title: `[Server] ${title}`,
          metadata: metadata || {}
        });
      }
    } catch {
    }
  }
};
var server_default = Server;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  ...require("./modules")
});
