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/solution/VenueBooking/index.ts
var VenueBooking_exports = {};
__export(VenueBooking_exports, {
  VenueBookingImpl: () => VenueBookingImpl
});
module.exports = __toCommonJS(VenueBooking_exports);
var import_BaseModule = require("../../modules/BaseModule");
var import_types = require("./types");
var import_utils = require("./utils");
var import_types2 = require("../BookingByStep/types");
var import_ProductList = require("../../modules/ProductList");
var import_Date = require("../../modules/Date");
var import_Schedule = require("../../modules/Schedule");
var import_utils2 = require("../../modules/Schedule/utils");
var import_Quotation = require("../../modules/Quotation");
var import_OpenData = require("../../modules/OpenData");
var import_types3 = require("../../modules/Account/types");
var import_dayjs = __toESM(require("dayjs"));
var import_itemRule = require("../../model/strategy/adapter/itemRule");
var import_resource = require("./utils/resource");
var import_timeSlot = require("./utils/timeSlot");
var import_dateSummary = require("./utils/dateSummary");
var import_slotMerge = require("./utils/slotMerge");
var import_utils3 = require("../../modules/Order/utils");
var import_Order = require("../../modules/Order");
var import_types4 = require("../RegisterAndLogin/types");
var import_decimal = __toESM(require("decimal.js"));
__reExport(VenueBooking_exports, require("./types"), module.exports);
var OPEN_DATA_SECTION_CODES = [
  "basic",
  "fulfillment",
  "reservation",
  "sale",
  "menu",
  "availability",
  "workflow",
  "checkout"
];
function cloneCustomDepositData(customDepositData) {
  if (!customDepositData || typeof customDepositData !== "object")
    return void 0;
  return {
    ...customDepositData,
    self_deposit_policy_ids: Array.isArray(customDepositData.self_deposit_policy_ids) ? [...customDepositData.self_deposit_policy_ids] : [],
    deposit_policy_ids: Array.isArray(customDepositData.deposit_policy_ids) ? [...customDepositData.deposit_policy_ids] : [],
    deposit_policy_data: Array.isArray(customDepositData.deposit_policy_data) ? [...customDepositData.deposit_policy_data] : []
  };
}
var _VenueBookingImpl = class extends import_BaseModule.BaseModule {
  constructor(name, version) {
    super(name, version);
    this.defaultName = "venueBooking";
    this.defaultVersion = "1.0.0";
    this.isSolution = true;
    this.initializeOptions = {};
    this.store = {
      entryContext: null,
      status: "idle",
      flow: {},
      error: null,
      products: void 0,
      rawResourceData: [],
      slotConfig: { ...import_types.DEFAULT_SLOT_CONFIG },
      itemRuleQuantityLimits: [],
      cartValidation: {
        passed: null,
        failures: []
      }
    };
    this.otherParams = {};
    this.baseSlotConfig = { ...import_types.DEFAULT_SLOT_CONFIG };
    this.itemRuleEvaluator = new import_itemRule.ItemRuleEvaluator();
    this.itemRuleConfigs = [];
    this.itemRuleConfigsPromise = null;
    this.itemRulePrefillApplied = false;
    this.itemRuleRuntimeConfig = {};
    this.resourceProductMap = /* @__PURE__ */ new Map();
    this.loginEffectDisposers = [];
    this.customerLoginRefreshInFlight = null;
    this.customerLoginRefreshIdInFlight = null;
    this.loadAllProductsInFlight = null;
    this.productsLoaded = false;
    this.loadOpenDataConfigInFlight = null;
  }
  getLoggerContext() {
    return {
      cacheId: this.cacheId,
      solutionName: this.name,
      moduleName: "venueBooking"
    };
  }
  safeStringify(value) {
    try {
      return JSON.stringify(value);
    } catch {
      return void 0;
    }
  }
  pickErrorMessage(error) {
    var _a, _b, _c, _d;
    const candidates = [
      error.message,
      (_a = error.data) == null ? void 0 : _a.message,
      (_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message,
      (_d = error.error) == null ? void 0 : _d.message
    ];
    for (const candidate of candidates) {
      if (typeof candidate === "string" && candidate.trim())
        return candidate;
    }
    return void 0;
  }
  serializeError(error) {
    if (error instanceof Error) {
      return {
        name: error.name,
        message: error.message,
        stack: error.stack
      };
    }
    if (error && typeof error === "object") {
      const raw = error;
      const message = this.pickErrorMessage(raw) || this.safeStringify(raw) || String(error);
      return {
        ...typeof raw.name === "string" ? { name: raw.name } : {},
        message,
        ..."code" in raw ? { code: raw.code } : {},
        ..."status" in raw ? { status: raw.status } : {},
        ...this.safeStringify(raw) ? { raw: this.safeStringify(raw) } : {}
      };
    }
    return {
      message: String(error)
    };
  }
  async addVenueBookingLog(params) {
    const payload = {
      cacheId: this.cacheId,
      ...params.payload || {}
    };
    const extra = {
      ...params.extra || {}
    };
    const logger = this.store.scanOrderLogger;
    if (!logger) {
      if ((params.level || "info") === "error") {
        console.error("[VenueBooking][log-fallback]", params.title, { payload, extra });
      } else {
        console.log("[VenueBooking][log-fallback]", params.title, { payload, extra });
      }
      return;
    }
    await logger.addLog({
      ...params,
      payload,
      extra
    });
  }
  logMethodStart(method, payload = {}) {
    void this.addVenueBookingLog({
      level: "info",
      title: `[VenueBooking] ${method} start`,
      payload: {
        method,
        ...payload
      }
    });
  }
  logMethodSuccess(method, payload = {}) {
    void this.addVenueBookingLog({
      level: "info",
      title: `[VenueBooking] ${method} success`,
      payload: {
        method,
        ...payload
      }
    });
  }
  logMethodError(method, error, payload = {}) {
    void this.addVenueBookingLog({
      level: "error",
      title: `[VenueBooking] ${method} failed`,
      payload: {
        method,
        ...payload,
        error: this.serializeError(error)
      }
    });
  }
  async addLog(params) {
    await this.addVenueBookingLog({
      ...params,
      payload: {
        source: "ui-bridge",
        ...params.payload || {}
      }
    });
  }
  normalizeCustomerId(value) {
    const customerId = Number(value);
    if (!Number.isFinite(customerId) || customerId <= 0)
      return null;
    return customerId;
  }
  resolveCustomerIdFromLoginPayload(payload) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i;
    const candidates = [
      payload == null ? void 0 : payload.customerId,
      payload == null ? void 0 : payload.customer_id,
      payload == null ? void 0 : payload.id,
      (_a = payload == null ? void 0 : payload.user) == null ? void 0 : _a.customerId,
      (_b = payload == null ? void 0 : payload.user) == null ? void 0 : _b.customer_id,
      (_c = payload == null ? void 0 : payload.user) == null ? void 0 : _c.id,
      (_e = (_d = payload == null ? void 0 : payload.user) == null ? void 0 : _d._origin) == null ? void 0 : _e.customer_id,
      (_f = payload == null ? void 0 : payload.account) == null ? void 0 : _f.customerId,
      (_g = payload == null ? void 0 : payload.account) == null ? void 0 : _g.customer_id,
      (_h = payload == null ? void 0 : payload.account) == null ? void 0 : _h.id,
      (_i = payload == null ? void 0 : payload._origin) == null ? void 0 : _i.customer_id
    ];
    for (const candidate of candidates) {
      const customerId = this.normalizeCustomerId(candidate);
      if (customerId)
        return customerId;
    }
    return null;
  }
  clearLoginEffectListeners() {
    for (const dispose of this.loginEffectDisposers) {
      dispose();
    }
    this.loginEffectDisposers = [];
  }
  registerLoginEffect(event, callback) {
    var _a;
    const effects = (_a = this.core) == null ? void 0 : _a.effects;
    if (!(effects == null ? void 0 : effects.on))
      return;
    effects.on(event, callback);
    this.loginEffectDisposers.push(() => {
      if (typeof effects.off === "function") {
        effects.off(event, callback);
      }
    });
  }
  registerCustomerLoginListeners() {
    var _a, _b, _c, _d;
    this.clearLoginEffectListeners();
    const accountModule = (_a = this.core) == null ? void 0 : _a.getModule("account");
    const registerAndLoginModule = (_b = this.core) == null ? void 0 : _b.getModule("registerAndLogin");
    const currentAccount = ((_c = accountModule == null ? void 0 : accountModule.getCurrentAccount) == null ? void 0 : _c.call(accountModule)) || ((_d = accountModule == null ? void 0 : accountModule.getAccount) == null ? void 0 : _d.call(accountModule)) || null;
    const createHandleLogin = (eventName) => async (payload) => {
      const customerId = this.resolveCustomerIdFromLoginPayload(payload);
      if (!customerId)
        return;
      await this.refreshOrderMarketingAfterLogin({ customerId });
    };
    this.registerLoginEffect(import_types3.AccountHooks.OnLogin, createHandleLogin(import_types3.AccountHooks.OnLogin));
    this.registerLoginEffect(import_types4.RegisterAndLoginHooks.onLoginSuccess, createHandleLogin(import_types4.RegisterAndLoginHooks.onLoginSuccess));
  }
  async refreshOrderMarketingAfterLogin(params) {
    if (!this.store.order)
      throw new Error("order 模块未初始化");
    if (this.customerLoginRefreshInFlight) {
      if (this.customerLoginRefreshIdInFlight === params.customerId) {
        await this.customerLoginRefreshInFlight;
        return;
      }
      await this.customerLoginRefreshInFlight;
    }
    this.customerLoginRefreshIdInFlight = params.customerId;
    const refreshTask = (async () => {
      var _a;
      if (this.store.quotation) {
        await this.store.quotation.loadQuotations({
          channel: (_a = this.otherParams) == null ? void 0 : _a.channel
        });
      }
      this.recalculateOrderPricesFromQuotation();
      await this.store.order.loadDiscountConfig({
        customerId: params.customerId
      });
      await this.store.order.recalculateSummary({ createIfMissing: true });
      this.store.order.persistTempOrder();
      await this.refreshItemRuleQuantityLimits();
      await this.refreshCartValidationPassed();
    })();
    this.customerLoginRefreshInFlight = refreshTask;
    try {
      await refreshTask;
    } catch (error) {
      throw error;
    } finally {
      if (this.customerLoginRefreshInFlight === refreshTask) {
        this.customerLoginRefreshInFlight = null;
        this.customerLoginRefreshIdInFlight = null;
      }
    }
  }
  async initialize(core, options = {}) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
    this.logMethodStart("initialize");
    this.core = core;
    this.initializeOptions = options || {};
    this.store = { ...this.store, ...options.store };
    this.store.entryContext = ((_a = options.otherParams) == null ? void 0 : _a.entryContext) || this.store.entryContext;
    this.store.status = "initializing";
    this.store.error = null;
    this.store.rawResourceData = [];
    this.baseSlotConfig = {
      ...import_types.DEFAULT_SLOT_CONFIG,
      ...((_b = options.otherParams) == null ? void 0 : _b.slotConfig) || {}
    };
    this.store.slotConfig = { ...this.baseSlotConfig };
    this.otherParams = options.otherParams || {};
    this.cacheId = (_c = this.otherParams) == null ? void 0 : _c.cacheId;
    this.itemRuleRuntimeConfig = ((_d = this.otherParams) == null ? void 0 : _d.venueBookingItemRule) || ((_e = this.otherParams) == null ? void 0 : _e.itemRule) || {};
    this.itemRuleConfigs = [];
    this.itemRuleConfigsPromise = null;
    this.itemRulePrefillApplied = false;
    this.store.itemRuleQuantityLimits = [];
    this.store.cartValidation = {
      passed: null,
      failures: []
    };
    this.window = core.getPlugin("window");
    this.request = core.getPlugin("request");
    if (!this.window) {
      this.logMethodError("initialize", "window plugin missing");
      throw new Error("venueBooking解决方案需要 window 插件支持");
    }
    if (!this.request) {
      this.logMethodError("initialize", "request plugin missing");
      throw new Error("venueBooking解决方案需要 request 插件支持");
    }
    const baseModules = [
      "scanOrderLogger",
      "products",
      "order",
      "salesSummary"
    ];
    baseModules.forEach((step) => {
      var _a2, _b2, _c2, _d2, _e2, _f2;
      const targetModule = (0, import_types2.createModule)(step, this.name);
      if (targetModule) {
        this.store[step] = targetModule;
        const initialState = step === "salesSummary" ? {
          summary: ((_b2 = (_a2 = this.store.order) == null ? void 0 : _a2.getTempOrder()) == null ? void 0 : _b2.summary) || (0, import_utils.createEmptySummary)()
        } : {};
        const loggerProvider = ((_c2 = this.otherParams) == null ? void 0 : _c2.loggerProvider) || "feishu";
        const loggerConfig = ((_d2 = this.otherParams) == null ? void 0 : _d2.loggerConfig) || {
          feishu: {
            webhook: "https://open.feishu.cn/open-apis/bot/v2/hook/8f069b14-9d39-4728-8f78-b56f393bfde8",
            errorHook: "https://open.feishu.cn/open-apis/bot/v2/hook/bdefae5e-f233-4705-8688-946887d9543d"
          }
        };
        this.core.registerModule(targetModule, {
          initialState,
          otherParams: {
            ...this.otherParams,
            fatherModule: this.name,
            openCache: ((_e2 = this.otherParams) == null ? void 0 : _e2.cacheId) ? true : false,
            cacheId: (_f2 = this.otherParams) == null ? void 0 : _f2.cacheId,
            salesSummaryModuleName: `${this.name}_salesSummary`,
            provider: loggerProvider,
            providerConfig: loggerConfig,
            context: this.getLoggerContext()
          }
        });
      } else {
        this.logMethodError("initialize", `module ${step} missing`);
        throw new Error(`模块 ${step} 不存在`);
      }
    });
    const venueProductsModule = new import_ProductList.ProductList(`${this.name}_venueProducts`);
    this.store.venueProducts = venueProductsModule;
    this.core.registerModule(venueProductsModule, {
      otherParams: {
        ...this.otherParams,
        fatherModule: this.name
      }
    });
    const addonProductsModule = new import_ProductList.ProductList(`${this.name}_addonProducts`);
    this.store.addonProducts = addonProductsModule;
    this.core.registerModule(addonProductsModule, {
      otherParams: {
        ...this.otherParams,
        fatherModule: this.name
      }
    });
    const dateModule = new import_Date.DateModule(`${this.name}_date`);
    this.store.date = dateModule;
    this.core.registerModule(dateModule, {
      otherParams: {
        ...this.otherParams,
        fatherModule: this.name,
        cacheId: this.cacheId
      }
    });
    const scheduleModule = new import_Schedule.ScheduleModule(`${this.name}_schedule`);
    this.store.schedule = scheduleModule;
    this.core.registerModule(scheduleModule, {
      otherParams: {
        ...this.otherParams,
        fatherModule: this.name
      }
    });
    const quotationModule = new import_Quotation.QuotationModule(`${this.name}_quotation`);
    this.store.quotation = quotationModule;
    this.core.registerModule(quotationModule, {
      otherParams: {
        ...this.otherParams,
        fatherModule: this.name
      }
    });
    const openDataModule = new import_OpenData.OpenDataModule(`${this.name}_openData`);
    this.store.openData = openDataModule;
    this.core.registerModule(openDataModule, {
      otherParams: {
        ...this.otherParams,
        fatherModule: this.name,
        openCache: !!((_f = this.otherParams) == null ? void 0 : _f.cacheId),
        cacheId: (_g = this.otherParams) == null ? void 0 : _g.cacheId
      }
    });
    if (this.store.scanOrderLogger) {
      this.store.scanOrderLogger.setContext(this.getLoggerContext());
    }
    this.registerCustomerLoginListeners();
    console.log("[VenueBooking] 初始化开始");
    try {
      await ((_h = this.store.order) == null ? void 0 : _h.recalculateSummary({ createIfMissing: false }));
      (_i = this.store.order) == null ? void 0 : _i.persistTempOrder();
      await this.loadRuntimeConfigs();
      if (this.store.schedule) {
        await this.store.schedule.loadAllSchedule();
        this.injectScheduleResolverToQuotation();
        (_k = this.store.quotation) == null ? void 0 : _k.loadQuotations({
          channel: (_j = this.otherParams) == null ? void 0 : _j.channel
        });
      }
      await this.refreshItemRuleQuantityLimits();
      this.store.status = "ready";
      console.log("[VenueBooking] 初始化完成");
      await this.core.effects.emit(import_types.VenueBookingHooks.onInited, {
        status: this.store.status
      });
      this.logMethodSuccess("initialize", {
        status: this.store.status
      });
    } catch (error) {
      this.store.status = "error";
      this.store.error = error instanceof Error ? error.message : "初始化失败";
      console.error("[VenueBooking] 初始化失败", error);
      this.logMethodError("initialize", error, {
        status: this.store.status
      });
      throw error;
    }
  }
  async destroy() {
    this.logMethodStart("destroy");
    this.clearLoginEffectListeners();
    await this.core.effects.emit(import_types.VenueBookingHooks.onDestroy, {});
    console.log("[VenueBooking] 已销毁");
    this.logMethodSuccess("destroy");
  }
  async retryInit() {
    this.logMethodStart("retryInit");
    console.log("[VenueBooking] retryInit 调用");
    await this.core.effects.emit(import_types.VenueBookingHooks.onRetryInit, {});
    try {
      await this.initialize(this.core, this.initializeOptions);
      this.logMethodSuccess("retryInit");
    } catch (error) {
      this.logMethodError("retryInit", error);
      throw error;
    }
  }
  async refresh() {
    this.logMethodStart("refresh");
    console.log("[VenueBooking] refresh 调用");
    try {
      this.store.status = "initializing";
      await this.loadRuntimeConfigs();
      await this.refreshItemRuleQuantityLimits();
      this.store.status = "ready";
      await this.core.effects.emit(import_types.VenueBookingHooks.onRefresh, {
        status: this.store.status
      });
      this.logMethodSuccess("refresh", {
        status: this.store.status
      });
    } catch (error) {
      this.logMethodError("refresh", error);
      throw error;
    }
  }
  // ─── 状态查询 ───
  getStatus() {
    return this.store.status;
  }
  getEntryContext() {
    return this.store.entryContext;
  }
  getItemRuleQuantityLimits() {
    return this.store.itemRuleQuantityLimits || [];
  }
  getCartValidationPassed() {
    var _a;
    return ((_a = this.store.cartValidation) == null ? void 0 : _a.passed) ?? null;
  }
  getCartValidation() {
    return this.store.cartValidation || { passed: null, failures: [] };
  }
  // ─── 场地商品 & 附加商品 ───
  async loadAllProducts() {
    if (this.loadAllProductsInFlight)
      return this.loadAllProductsInFlight;
    this.loadAllProductsInFlight = this._doLoadAllProducts().finally(() => {
      this.loadAllProductsInFlight = null;
    });
    return this.loadAllProductsInFlight;
  }
  async _doLoadAllProducts() {
    var _a, _b, _c;
    this.logMethodStart("loadAllProducts");
    try {
      if (!this.store.venueProducts)
        throw new Error("venueProducts 模块未初始化");
      if (!this.store.addonProducts)
        throw new Error("addonProducts 模块未初始化");
      await this.loadOpenDataConfig();
      const associatedMenus = ((_b = (_a = this.otherParams) == null ? void 0 : _a.openData) == null ? void 0 : _b["menu.associated_menus"]) || [];
      if (!associatedMenus.length) {
        this.logMethodError("loadAllProducts", new Error("未获取到餐牌配置（menu.associated_menus），请检查 OpenData 配置"));
        throw new Error("未获取到餐牌配置（menu.associated_menus），请检查 OpenData 配置");
      }
      const menuListIds = associatedMenus.map((n) => Number(n.value));
      const allProducts = await this.store.venueProducts.loadProducts({
        menu_list_ids: menuListIds,
        cacheId: this.cacheId,
        schedule_date: (0, import_dayjs.default)().format("YYYY-MM-DD"),
        schedule_datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
      });
      const list = Array.isArray(allProducts) ? allProducts : [];
      const venueList = list.filter((p) => p.duration != null);
      const addonList = list.filter((p) => p.duration == null);
      const venueStore = (_c = this.store.venueProducts) == null ? void 0 : _c.store;
      if (venueStore) {
        venueStore.list = venueList.slice().sort((a, b) => Number(b.sort) - Number(a.sort));
      }
      this.store.addonProducts.addProduct(addonList);
      this.resourceProductMap = (0, import_resource.buildResourceProductMap)(venueList);
      this.productsLoaded = true;
      this.logMethodSuccess("loadAllProducts", {
        total: list.length,
        venueCount: venueList.length,
        addonCount: addonList.length,
        resourceCount: this.resourceProductMap.size
      });
      return { venueProducts: venueList, addonProducts: addonList };
    } catch (error) {
      this.logMethodError("loadAllProducts", error);
      throw error;
    }
  }
  async loadVenueProducts() {
    const result = await this.loadAllProducts();
    return result.venueProducts;
  }
  async loadAddonProducts() {
    const result = await this.loadAllProducts();
    return result.addonProducts;
  }
  getVenueProducts() {
    var _a, _b;
    return ((_b = (_a = this.store.venueProducts) == null ? void 0 : _a.store) == null ? void 0 : _b.list) || [];
  }
  getAddonProductsList() {
    var _a, _b;
    return ((_b = (_a = this.store.addonProducts) == null ? void 0 : _a.store) == null ? void 0 : _b.list) || [];
  }
  // ─── 报价单 ───
  async loadQuotations(params) {
    this.logMethodStart("loadQuotations");
    try {
      if (!this.store.quotation)
        throw new Error("quotation 模块未初始化");
      await this.store.quotation.loadQuotations(params);
      this.logMethodSuccess("loadQuotations", {
        count: this.store.quotation.getQuotationList().length
      });
    } catch (error) {
      this.logMethodError("loadQuotations", error);
      throw error;
    }
  }
  // ─── 资源可用性 ───
  async fetchResourceAvailability(params) {
    this.logMethodStart("fetchResourceAvailability", params);
    try {
      const venueProducts = this.getVenueProducts();
      if (!venueProducts.length) {
        this.store.rawResourceData = [];
        this.logMethodSuccess("fetchResourceAvailability", { resourceCount: 0 });
        return;
      }
      const resourceIds = (0, import_resource.extractResourceIds)(venueProducts);
      if (!resourceIds.length) {
        this.store.rawResourceData = [];
        this.logMethodSuccess("fetchResourceAvailability", { resourceIds: [] });
        return;
      }
      const config = this.store.slotConfig;
      const crossDay = (0, import_timeSlot.isBusinessHoursCrossDay)(config);
      const effectiveEndDate = crossDay ? (0, import_dayjs.default)(params.endDate).add(1, "day").format("YYYY-MM-DD") : params.endDate;
      if (!this.store.date)
        throw new Error("date 模块未初始化");
      const res = await this.store.date.fetchResourceDates({
        query: {
          start_date: params.startDate,
          end_date: effectiveEndDate,
          resource_ids: resourceIds
        },
        useCache: false
      });
      const rawData = [];
      if ((res == null ? void 0 : res.data) && Array.isArray(res.data)) {
        for (const item of res.data) {
          rawData.push({
            resourceId: item.id,
            formId: item.form_id,
            times: Array.isArray(item.times) ? item.times : [],
            ...item
          });
        }
      }
      this.store.rawResourceData = rawData;
      for (const item of rawData) {
        const mappings = this.resourceProductMap.get(item.resourceId);
        if (!mappings)
          continue;
        for (const mapping of mappings) {
          if (item.main_field)
            mapping.resourceName = item.main_field;
          if (item.resource_form_id)
            mapping.formId = item.resource_form_id;
        }
      }
      this.logMethodSuccess("fetchResourceAvailability", {
        resourceCount: rawData.length,
        totalTimes: rawData.reduce((sum, r) => sum + r.times.length, 0)
      });
    } catch (error) {
      this.store.rawResourceData = [];
      this.logMethodError("fetchResourceAvailability", error);
      throw error;
    }
  }
  // ─── 日期概览 & 时间槽矩阵（纯计算，不发请求） ───
  getOperatingHoursScheduleIds() {
    var _a, _b;
    const openData = this.otherParams.openData || ((_b = (_a = this.store.openData) == null ? void 0 : _a.getOpenData) == null ? void 0 : _b.call(_a)) || null;
    const rawIds = openData == null ? void 0 : openData["availability.operating_hours"];
    if (!Array.isArray(rawIds))
      return [];
    return [...new Set(
      rawIds.map((id) => Number(id)).filter((id) => Number.isFinite(id) && id > 0).map((id) => Math.floor(id))
    )];
  }
  resolveSlotConfigForDate(date) {
    var _a;
    const nextSlotConfig = { ...this.baseSlotConfig };
    if (!date || !this.store.schedule)
      return nextSlotConfig;
    const operatingHoursScheduleIds = this.getOperatingHoursScheduleIds();
    if (!operatingHoursScheduleIds.length)
      return nextSlotConfig;
    const scheduleList = this.store.schedule.getScheduleListByIds(
      operatingHoursScheduleIds
    );
    if (!scheduleList.length)
      return nextSlotConfig;
    const timeRangeMap = (0, import_utils2.calcMinTimeMaxTimeBySchedules)(
      scheduleList,
      void 0,
      date
    );
    let earliestStart = null;
    let latestEnd = null;
    for (const schedule of scheduleList) {
      const dateRangeList = ((_a = timeRangeMap == null ? void 0 : timeRangeMap[schedule.id]) == null ? void 0 : _a.dateRangeFormat) || [];
      for (const range of dateRangeList) {
        const start = (0, import_dayjs.default)(range == null ? void 0 : range.start);
        const end = (0, import_dayjs.default)(range == null ? void 0 : range.end);
        if (!start.isValid() || !end.isValid())
          continue;
        if (!earliestStart || start.isBefore(earliestStart)) {
          earliestStart = start;
        }
        if (!latestEnd || end.isAfter(latestEnd)) {
          latestEnd = end;
        }
      }
    }
    if (!earliestStart || !latestEnd)
      return nextSlotConfig;
    return {
      ...nextSlotConfig,
      businessStartTime: earliestStart.format("HH:mm"),
      businessEndTime: latestEnd.format("HH:mm")
    };
  }
  syncOperatingHoursToSlotConfig(date) {
    const resolvedSlotConfig = this.resolveSlotConfigForDate(date);
    this.store.slotConfig = resolvedSlotConfig;
    return resolvedSlotConfig;
  }
  getDateRangeSummary(params) {
    return (0, import_dateSummary.buildDateRangeSummary)({
      startDate: params.startDate,
      endDate: params.endDate,
      config: this.baseSlotConfig,
      rawResources: this.store.rawResourceData,
      resourceProductMap: this.resourceProductMap,
      quotationModule: this.store.quotation,
      resolveConfig: (date) => this.resolveSlotConfigForDate(date)
    });
  }
  getTimeSlotGrid(date) {
    const resolvedSlotConfig = this.syncOperatingHoursToSlotConfig(date);
    let quotationPriceMap;
    if (this.store.quotation) {
      const productIds = [
        ...new Set(
          [...this.resourceProductMap.values()].flat().map((m) => m.productId)
        )
      ];
      const timeLabels = (0, import_timeSlot.generateTimeLabels)(resolvedSlotConfig);
      const timePoints = timeLabels.map((label) => `${date} ${label}`);
      quotationPriceMap = this.store.quotation.buildProductPriceMap({ productIds, timePoints });
    }
    return (0, import_timeSlot.buildTimeSlotGrid)({
      date,
      config: resolvedSlotConfig,
      rawResources: this.store.rawResourceData,
      resourceProductMap: this.resourceProductMap,
      quotationPriceMap
    });
  }
  // ─── 时间槽订单操作 ───
  /**
   * 切换单个时段的选中状态（选中/取消）。
   * 内部自动处理连续时段的合并与拆分，订单是唯一真相源。
   *
   * slot.productId 指定当前操作针对的是该 resourceId 下的哪一个商品。
   * 同一资源下不同 productId 之间互相隔离，不会相互合并。
   */
  async toggleSlot(slot) {
    this.logMethodStart("toggleSlot", {
      resourceId: slot.resourceId,
      productId: slot.productId,
      startTime: slot.startTime
    });
    try {
      const mappings = this.resourceProductMap.get(slot.resourceId);
      if (!mappings || !mappings.length) {
        throw new Error(`未找到资源 ${slot.resourceId} 的商品映射`);
      }
      const mapping = mappings.find((m) => m.productId === slot.productId);
      if (!mapping) {
        throw new Error(`资源 ${slot.resourceId} 未关联商品 ${slot.productId}`);
      }
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const currentSlots = this.getSelectedSlotsForResourceProduct(
        slot.resourceId,
        slot.productId
      );
      const existIndex = currentSlots.findIndex((s) => s.startTime === slot.startTime);
      let nextSlots;
      if (existIndex !== -1) {
        nextSlots = currentSlots.filter((_, i) => i !== existIndex);
      } else {
        nextSlots = [...currentSlots, slot];
      }
      await this.reconcileOrderForResourceProduct(
        slot.resourceId,
        slot.productId,
        nextSlots
      );
      const products = this.store.order.getOrderProducts();
      await this.refreshItemRuleQuantityLimits();
      await this.refreshCartValidationPassed();
      this.logMethodSuccess("toggleSlot", {
        action: existIndex !== -1 ? "remove" : "add",
        resourceId: slot.resourceId,
        productId: slot.productId,
        slotCount: nextSlots.length
      });
      return products;
    } catch (error) {
      this.logMethodError("toggleSlot", error);
      throw error;
    }
  }
  /**
   * 获取某资源当前选中的所有独立时段（从订单中解析）。
   * 不传 productId 时返回该资源下所有商品的选中时段；传了则精确匹配。
   */
  getSelectedSlotsForResource(resourceId, productId) {
    var _a;
    const tempOrder = (_a = this.store.order) == null ? void 0 : _a.getTempOrder();
    if (!tempOrder)
      return [];
    const venueProducts = tempOrder.products.filter((p) => {
      var _a2, _b;
      if (!((_a2 = p.metadata) == null ? void 0 : _a2.venue_booking))
        return false;
      if (String((_b = p.metadata) == null ? void 0 : _b.resource_id) !== String(resourceId))
        return false;
      if (productId != null && Number(p.product_id) !== Number(productId))
        return false;
      return true;
    });
    const slotDuration = this.store.slotConfig.slotDurationMinutes;
    const slots = [];
    for (const product of venueProducts) {
      slots.push(
        ...(0, import_slotMerge.expandMergedSlotToIndividual)(product, slotDuration).map((s) => ({
          ...s,
          productId: Number(product.product_id)
        }))
      );
    }
    return slots.sort((a, b) => a.startTime.localeCompare(b.startTime));
  }
  /** getSelectedSlotsForResource 的 (resourceId, productId) 精确版，内部使用。 */
  getSelectedSlotsForResourceProduct(resourceId, productId) {
    return this.getSelectedSlotsForResource(resourceId, productId);
  }
  /**
   * 判断某个时段是否已选中。
   * 不传 productId 时：只要该资源下任一商品在 startTime 被选中即返回 true；传了则精确匹配。
   */
  isSlotSelected(resourceId, startTime, productId) {
    return this.getSelectedSlotsForResource(resourceId, productId).some((s) => s.startTime === startTime);
  }
  /**
   * 判断指定 (resourceId, productId, startTime) 格子是否应因其它已选项而被禁用。
   * 规则：
   * 1) 同一 resourceId 下若已选了另一个 productId 的同 startTime → 禁用
   * 2) 当前 resource 是组合资源：若其任一 child resource 在 startTime 被选中 → 禁用
   * 3) 当前 resource 是某些组合资源的 child：若该组合资源在 startTime 被选中 → 禁用
   * 4) 两个组合资源的 child 集合有交集，且对方在该 startTime 被选中 → 禁用
   */
  isSlotDisabledBySelection(params) {
    const { resourceId, productId, startTime } = params;
    const allSelected = this.getAllSelectedSlots();
    const getSelectedAt = (resId) => {
      const list = allSelected.get(resId) || [];
      return list.filter((s) => s.startTime === startTime);
    };
    const sameResourceSelections = getSelectedAt(resourceId);
    if (sameResourceSelections.some((s) => Number(s.productId) !== Number(productId))) {
      return true;
    }
    const getCombinedChildIds = (resId) => {
      const raw = this.store.rawResourceData.find(
        (r) => String(r.resourceId) === String(resId)
      );
      const combined = raw == null ? void 0 : raw.combined_resource;
      if (combined && combined.status === 1 && Array.isArray(combined.resource_ids)) {
        return combined.resource_ids;
      }
      return [];
    };
    const currentChildIds = getCombinedChildIds(resourceId);
    const currentIsCombined = currentChildIds.length > 0;
    if (currentIsCombined) {
      for (const childId of currentChildIds) {
        if (getSelectedAt(childId).length > 0)
          return true;
      }
    }
    for (const [selectedResId, slots] of allSelected) {
      if (!slots.some((s) => s.startTime === startTime))
        continue;
      if (String(selectedResId) === String(resourceId))
        continue;
      const selectedChildIds = getCombinedChildIds(selectedResId);
      if (selectedChildIds.length === 0)
        continue;
      if (selectedChildIds.some((id) => String(id) === String(resourceId))) {
        return true;
      }
      if (currentIsCombined) {
        const intersect = selectedChildIds.some(
          (id) => currentChildIds.some((cid) => String(cid) === String(id))
        );
        if (intersect)
          return true;
      }
    }
    return false;
  }
  /**
   * 获取所有已选时段（按资源分组）。每个 slot 上带 productId，便于 UI 做 per-product 判定。
   */
  getAllSelectedSlots() {
    var _a, _b;
    const result = /* @__PURE__ */ new Map();
    const tempOrder = (_a = this.store.order) == null ? void 0 : _a.getTempOrder();
    if (!tempOrder)
      return result;
    const venueProducts = tempOrder.products.filter((p) => {
      var _a2;
      return (_a2 = p.metadata) == null ? void 0 : _a2.venue_booking;
    });
    const slotDuration = this.store.slotConfig.slotDurationMinutes;
    for (const product of venueProducts) {
      const resourceId = (_b = product.metadata) == null ? void 0 : _b.resource_id;
      if (resourceId == null)
        continue;
      const productId = Number(product.product_id);
      const existing = result.get(resourceId) || [];
      existing.push(
        ...(0, import_slotMerge.expandMergedSlotToIndividual)(product, slotDuration).map((s) => ({
          ...s,
          productId
        }))
      );
      result.set(resourceId, existing);
    }
    for (const [key, slots] of result) {
      result.set(key, slots.sort((a, b) => a.startTime.localeCompare(b.startTime)));
    }
    return result;
  }
  /**
   * 对指定 (resourceId, productId) 的订单商品进行 reconcile：
   * 清除旧商品 → 合并连续时段 → 重新写入。
   * 同一场地下不同商品互不干扰，各自单独 reconcile。
   */
  async reconcileOrderForResourceProduct(resourceId, productId, slots) {
    const mappings = this.resourceProductMap.get(resourceId);
    if (!mappings || !mappings.length || !this.store.order)
      return;
    const mapping = mappings.find((m) => m.productId === productId);
    if (!mapping)
      return;
    const tempOrder = this.store.order.ensureTempOrder();
    const matchesCurrent = (meta, pid) => !!(meta == null ? void 0 : meta.venue_booking) && String(meta == null ? void 0 : meta.resource_id) === String(resourceId) && Number(pid) === Number(productId);
    tempOrder.products = tempOrder.products.filter(
      (p) => !matchesCurrent(p.metadata, p.product_id)
    );
    tempOrder.bookings = (tempOrder.bookings || []).filter(
      (b) => {
        var _a, _b, _c, _d;
        if (!((_a = b.metadata) == null ? void 0 : _a.venue_booking))
          return true;
        if (String((_b = b.metadata) == null ? void 0 : _b.resource_id) !== String(resourceId))
          return true;
        const bookingProductId = ((_c = b.metadata) == null ? void 0 : _c.product_id) ?? ((_d = b == null ? void 0 : b.product) == null ? void 0 : _d.product_id);
        if (bookingProductId == null)
          return false;
        return Number(bookingProductId) !== Number(productId);
      }
    );
    if (!slots.length) {
      this.store.order.applyDiscount();
      await this.store.order.recalculateSummary({ createIfMissing: true });
      this.store.order.persistTempOrder();
      return;
    }
    const merged = (0, import_slotMerge.mergeConsecutiveSlots)(slots);
    const rawResource = this.store.rawResourceData.find(
      (r) => String(r.resourceId) === String(resourceId)
    );
    const childRawResources = this.getCombinedChildRawResources(rawResource);
    const venueProduct = this.getVenueProducts().find((p) => p.id === mapping.productId);
    tempOrder.bookings = tempOrder.bookings || [];
    for (let i = 0; i < merged.length; i++) {
      const group = merged[i];
      const identityKey = (0, import_slotMerge.buildVenueIdentityKey)(resourceId, i);
      const bookingUuid = (0, import_utils3.createUuidV4)();
      const startMoment = (0, import_dayjs.default)(group.startTime, "YYYY-MM-DD HH:mm");
      const endMoment = (0, import_dayjs.default)(group.endTime, "YYYY-MM-DD HH:mm");
      const duration = endMoment.diff(startMoment, "minute");
      const customDepositData = cloneCustomDepositData(venueProduct == null ? void 0 : venueProduct.custom_deposit_data);
      const resourceEntry = {
        relation_type: "form",
        like_status: "common",
        id: resourceId,
        main_field: mapping.resourceName,
        form_id: (rawResource == null ? void 0 : rawResource.form_id) ?? mapping.formId,
        relation_id: resourceId,
        capacity: 1,
        metadata: (0, import_slotMerge.buildVenueResourceMetadata)({ mapping, rawResource })
      };
      if (childRawResources && childRawResources.length) {
        resourceEntry.children = childRawResources.map((child) => ({
          relation_type: "form",
          like_status: "common",
          id: child.resourceId,
          main_field: child.main_field || "",
          form_id: child.form_id ?? child.formId,
          relation_id: child.resourceId,
          capacity: child.capacity ?? 1,
          metadata: {}
        }));
      }
      tempOrder.products.push(
        (0, import_utils.normalizeOrderProduct)({
          product_id: mapping.productId,
          product_variant_id: 0,
          identity_key: identityKey,
          num: 1,
          selling_price: group.totalPrice,
          original_price: group.totalPrice,
          is_charge_tax: (venueProduct == null ? void 0 : venueProduct.is_charge_tax) ?? 0,
          metadata: {
            venue_booking: true,
            resource_id: resourceId,
            resource_form_id: mapping.formId,
            resource_name: mapping.resourceName,
            start_time: group.startTime,
            end_time: group.endTime,
            slot_count: group.slotCount,
            booking_uid: bookingUuid,
            price_breakdown: (0, import_slotMerge.buildPriceBreakdown)({
              group,
              productId: mapping.productId,
              quotation: this.store.quotation
            })
          },
          _origin: {
            name: mapping.productTitle,
            cover: (venueProduct == null ? void 0 : venueProduct.cover) || "",
            custom_deposit_data: customDepositData,
            id: 0,
            number: 1,
            registration_type: "all",
            relation_products: [],
            is_all: false,
            product: {
              product_id: mapping.productId,
              product_variant_id: 0,
              num: 1,
              product_bundle: [],
              product_sku: { option: [] },
              discount_list: [],
              custom_deposit_data: customDepositData,
              metadata: {}
            },
            sub_type: "minutes",
            duration,
            like_status: "common",
            resources: [resourceEntry],
            schedule_id: 0,
            select_date: startMoment.format("YYYY-MM-DD"),
            start_date: startMoment.format("YYYY-MM-DD"),
            start_time: startMoment.format("HH:mm"),
            end_date: endMoment.format("YYYY-MM-DD"),
            end_time: endMoment.format("HH:mm"),
            metadata: {
              venue_booking: true,
              slot_count: group.slotCount
            },
            holder: null
          }
        })
      );
      const booking = (0, import_slotMerge.buildVenueBookingEntry)({
        group,
        resourceId,
        mapping,
        rawResource,
        bookingUuid,
        productUid: identityKey,
        childResources: childRawResources
      });
      tempOrder.bookings.push(booking);
    }
    this.store.order.applyDiscount();
    await this.store.order.recalculateSummary({ createIfMissing: true });
    this.store.order.persistTempOrder();
  }
  /** 给定一个父 rawResource，返回其 combined_resource.resource_ids 对应的子 rawResource 列表。 */
  getCombinedChildRawResources(rawResource) {
    if (!rawResource)
      return void 0;
    const combined = rawResource.combined_resource;
    if (!combined || combined.status !== 1 || !Array.isArray(combined.resource_ids) || !combined.resource_ids.length) {
      return void 0;
    }
    const children = [];
    for (const id of combined.resource_ids) {
      const child = this.store.rawResourceData.find(
        (r) => String(r.resourceId) === String(id)
      );
      if (child)
        children.push(child);
    }
    return children.length ? children : void 0;
  }
  // ─── 配置 ───
  setSlotConfig(config) {
    this.baseSlotConfig = {
      ...this.baseSlotConfig,
      ...config
    };
    this.store.slotConfig = {
      ...this.baseSlotConfig
    };
  }
  getSlotConfig() {
    return { ...this.store.slotConfig };
  }
  // ─── 日程 ───
  async loadSchedules() {
    this.logMethodStart("loadSchedules");
    try {
      if (!this.store.schedule)
        throw new Error("schedule 模块未初始化");
      await this.store.schedule.loadAllSchedule();
      this.injectScheduleResolverToQuotation();
      this.logMethodSuccess("loadSchedules");
    } catch (error) {
      this.logMethodError("loadSchedules", error);
      throw error;
    }
  }
  injectScheduleResolverToQuotation() {
    if (this.store.quotation && this.store.schedule) {
      this.store.quotation.setScheduleResolver(
        (id) => this.store.schedule.getScheduleListByIds([id])[0]
      );
    }
  }
  getScheduleListByIds(ids) {
    if (!this.store.schedule)
      return [];
    return this.store.schedule.getScheduleListByIds(ids);
  }
  // ─── 临时订单操作（保留原有能力） ───
  getTempOrder() {
    var _a;
    const result = ((_a = this.store.order) == null ? void 0 : _a.getTempOrder()) || null;
    return result;
  }
  updateTempOrderNote(note) {
    if (!this.store.order)
      throw new Error("order 模块未初始化");
    return this.store.order.updateTempOrderNote(note);
  }
  updateTempOrderContactsInfo(contactsInfo) {
    if (!this.store.order)
      throw new Error("order 模块未初始化");
    return this.store.order.updateTempOrderContactsInfo(contactsInfo);
  }
  ensureTempOrder() {
    if (!this.store.order)
      throw new Error("order 模块未初始化");
    return this.store.order.ensureTempOrder();
  }
  async onCustomerLogin(params) {
    this.logMethodStart("onCustomerLogin", { customerId: params.customerId });
    try {
      await this.refreshOrderMarketingAfterLogin({
        customerId: params.customerId
      });
      this.logMethodSuccess("onCustomerLogin", { customerId: params.customerId });
    } catch (error) {
      this.logMethodError("onCustomerLogin", error);
      throw error;
    }
  }
  recalculateOrderPricesFromQuotation() {
    var _a, _b;
    if (!this.store.order || !this.store.quotation)
      return;
    const tempOrder = this.store.order.getTempOrder();
    if (!((_a = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _a.length))
      return;
    const now = (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss");
    for (const product of tempOrder.products) {
      if ((_b = product.metadata) == null ? void 0 : _b.venue_booking) {
        const mappings = this.resourceProductMap.get(product.metadata.resource_id);
        if (!mappings || !mappings.length)
          continue;
        const mapping = mappings.find((m) => Number(m.productId) === Number(product.product_id)) || mappings[0];
        if (!mapping)
          continue;
        const slots = (0, import_slotMerge.expandMergedSlotToIndividual)(
          product,
          this.store.slotConfig.slotDurationMinutes
        );
        const updatedSlots = slots.map((slot) => ({
          ...slot,
          productId: mapping.productId,
          price: this.store.quotation.getPriceForProduct({
            productId: mapping.productId,
            datetime: slot.startTime
          }) ?? mapping.price
        }));
        const merged = (0, import_slotMerge.mergeConsecutiveSlots)(updatedSlots);
        if (merged.length === 1) {
          product.selling_price = merged[0].totalPrice;
          product.original_price = merged[0].totalPrice;
          product.metadata.price_breakdown = (0, import_slotMerge.buildPriceBreakdown)({
            group: merged[0],
            productId: mapping.productId,
            quotation: this.store.quotation
          });
        }
      } else if (product.product_id != null) {
        const quotationPrice = this.store.quotation.getPriceForProduct({
          productId: product.product_id,
          variantId: product.product_variant_id ?? void 0,
          datetime: now
        });
        if (quotationPrice !== null) {
          product.selling_price = quotationPrice;
          product.original_price = quotationPrice;
        }
      }
    }
  }
  async scanCode(code, customerId) {
    this.logMethodStart("scanCode", { code });
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const result = await this.store.order.scanCode(code, customerId);
      if (result.isAvailable) {
        await this.store.order.recalculateSummary({ createIfMissing: true });
        this.store.order.persistTempOrder();
      }
      this.logMethodSuccess("scanCode", { isAvailable: result.isAvailable });
      return result;
    } catch (error) {
      this.logMethodError("scanCode", error);
      throw error;
    }
  }
  /** 获取当前折扣列表（包装 order.getDiscountList） */
  getDiscountList() {
    if (!this.store.order)
      return [];
    return this.store.order.getDiscountList();
  }
  /** 勾选/取消勾选某张折扣券，重新计算折扣并持久化 */
  async setDiscountSelected(params) {
    var _a, _b, _c, _d, _e, _f, _g, _h;
    this.logMethodStart("setDiscountSelected", params);
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const list = this.store.order.getDiscountList();
      const beforeTarget = list.find((d) => d.id === params.discountId) || null;
      const updated = list.map(
        (d) => d.id === params.discountId ? {
          ...d,
          isSelected: params.isSelected,
          isManualSelect: !params.isSelected
        } : d
      );
      const updatedTarget = updated.find((d) => d.id === params.discountId) || null;
      const tempOrder = this.store.order.ensureTempOrder();
      const orderStore = this.store.order.store || {};
      const discountModule = orderStore.discount;
      const rulesModule = orderStore.rules;
      const holders = ((_a = tempOrder.holder) == null ? void 0 : _a.form_record_id) ? [{ form_record_id: tempOrder.holder.form_record_id }] : [];
      let nextDiscountList = updated;
      await (discountModule == null ? void 0 : discountModule.setDiscountList(updated));
      if (rulesModule) {
        const result = rulesModule.calcDiscount(
          {
            productList: tempOrder.products,
            discountList: updated,
            holders,
            isFormSubject: !!((_b = tempOrder.holder) == null ? void 0 : _b.type) && tempOrder.holder.type === "form"
          },
          {
            discountId: params.discountId,
            isSelected: params.isSelected
          }
        ) || { productList: tempOrder.products, discountList: updated };
        if (result == null ? void 0 : result.productList) {
          tempOrder.products = result.productList;
        }
        if (result == null ? void 0 : result.discountList) {
          nextDiscountList = result.discountList;
          if (!params.isSelected) {
            const beforeSelectedIds = new Set(
              updated.filter((d) => d.isSelected).map((d) => d.id)
            );
            for (const d of nextDiscountList) {
              if (d.isSelected && !beforeSelectedIds.has(d.id)) {
                d.isSelected = false;
              }
            }
          }
        }
      }
      const selectedResourceIds = new Set(
        nextDiscountList.filter((d) => d.isSelected).map((d) => d.id)
      );
      for (const product of tempOrder.products) {
        if ((_c = product._origin) == null ? void 0 : _c.isManualDiscount)
          continue;
        product.discount_list = (product.discount_list || []).filter((pd) => {
          var _a2;
          const rid = ((_a2 = pd.discount) == null ? void 0 : _a2.resource_id) ?? pd.id;
          return rid != null && selectedResourceIds.has(rid);
        });
        const totalPerUnitDiscount = (product.discount_list || []).reduce(
          (sum, pd) => sum + (pd.amount || 0),
          0
        );
        const optionSum = (0, import_utils3.sumOptionUnitPrice)((0, import_utils3.getProductSkuOptions)(product));
        const sourcePrice = ((_d = product.metadata) == null ? void 0 : _d.source_product_price) ?? (((_e = product.metadata) == null ? void 0 : _e.main_product_original_price) != null ? new import_decimal.default(Number(product.metadata.main_product_original_price) || 0).minus(optionSum).toFixed(2) : product.original_price ?? "0");
        const newSourceSellingPrice = new import_decimal.default(Number(sourcePrice) || 0).minus(totalPerUnitDiscount).toDecimalPlaces(2).toString();
        const newMainSellingPrice = new import_decimal.default(Number(newSourceSellingPrice) || 0).plus(optionSum).toDecimalPlaces(2).toFixed(2);
        if (product.metadata) {
          product.metadata.main_product_selling_price = newMainSellingPrice;
          product.metadata.price_schema_version = 2;
        }
        product.selling_price = (0, import_utils3.composeLinePrice)({
          mainPrice: newMainSellingPrice,
          bundle: product.product_bundle
        });
      }
      import_Order.OrderModule.populateSavedAmounts(tempOrder.products, nextDiscountList);
      await (discountModule == null ? void 0 : discountModule.setDiscountList(nextDiscountList));
      tempOrder.discount_list = (nextDiscountList || []).filter((d) => d.isSelected);
      const afterApplyTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
      await this.store.order.recalculateSummary({ createIfMissing: true });
      this.store.order.persistTempOrder();
      const finalSummary = ((_f = this.store.order.getTempOrder()) == null ? void 0 : _f.summary) || null;
      const finalProduct = ((_h = (_g = this.store.order.getTempOrder()) == null ? void 0 : _g.products) == null ? void 0 : _h[0]) || null;
      this.logMethodSuccess("setDiscountSelected", params);
      const finalTarget = this.store.order.getDiscountList().find((d) => d.id === params.discountId) || null;
      return this.store.order.getDiscountList();
    } catch (error) {
      this.logMethodError("setDiscountSelected", error);
      throw error;
    }
  }
  async addNewOrder() {
    this.logMethodStart("addNewOrder");
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const tempOrder = await this.store.order.addNewOrder();
      this.logMethodSuccess("addNewOrder", {
        productCount: tempOrder.products.length
      });
      return tempOrder;
    } catch (error) {
      this.logMethodError("addNewOrder", error);
      throw error;
    }
  }
  getOrderProducts() {
    if (!this.store.order)
      throw new Error("order 模块未初始化");
    const products = this.store.order.getOrderProducts();
    return products;
  }
  async getSummary() {
    this.logMethodStart("getSummary");
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const summary = await this.store.order.getOrderSummary();
      this.logMethodSuccess("getSummary", {
        totalAmount: summary.total_amount
      });
      return summary;
    } catch (error) {
      this.logMethodError("getSummary", error);
      throw error;
    }
  }
  async submitOrder() {
    var _a, _b, _c, _d, _e;
    this.logMethodStart("submitOrder");
    try {
      await this.validateBeforeSubmitByItemRule();
      if (!this.store.order) {
        throw new Error("venueBooking解决方案需要 order 模块支持");
      }
      const result = await this.store.order.submitTempOrder({
        cacheId: this.cacheId,
        platform: (_a = this.otherParams) == null ? void 0 : _a.platform,
        businessCode: (_b = this.otherParams) == null ? void 0 : _b.businessCode,
        channel: (_c = this.otherParams) == null ? void 0 : _c.channel,
        type: (_d = this.otherParams) == null ? void 0 : _d.type
      });
      const tempOrder = this.store.order.getTempOrder();
      this.logMethodSuccess("submitOrder", {
        productCount: ((_e = tempOrder == null ? void 0 : tempOrder.products) == null ? void 0 : _e.length) || 0
      });
      return result;
    } catch (error) {
      this.logMethodError("submitOrder", error);
      throw error;
    }
  }
  async addProductToOrder(product) {
    var _a;
    this.logMethodStart("addProductToOrder", {
      product_id: product.product_id,
      product_variant_id: product.product_variant_id
    });
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      if (!((_a = product.metadata) == null ? void 0 : _a.venue_booking) && this.store.quotation && product.product_id != null) {
        const quotationPrice = this.store.quotation.getPriceForProduct({
          productId: product.product_id,
          variantId: product.product_variant_id ?? void 0,
          datetime: (0, import_dayjs.default)().format("YYYY-MM-DD HH:mm:ss")
        });
        if (quotationPrice !== null) {
          product.selling_price = quotationPrice;
          product.original_price = quotationPrice;
        } else if (product.selling_price != null) {
          product.original_price = product.selling_price;
        }
      }
      const products = await this.store.order.addProductToOrder(product);
      await this.refreshItemRuleQuantityLimits();
      await this.refreshCartValidationPassed();
      this.logMethodSuccess("addProductToOrder", {
        productCount: products.length
      });
      return products;
    } catch (error) {
      this.logMethodError("addProductToOrder", error);
      throw error;
    }
  }
  async updateOrderProduct(params) {
    this.logMethodStart("updateOrderProduct", {
      product_id: params.product_id,
      product_variant_id: params.product_variant_id
    });
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const products = await this.store.order.updateOrderProduct(params);
      await this.refreshItemRuleQuantityLimits();
      await this.refreshCartValidationPassed();
      this.logMethodSuccess("updateOrderProduct", {
        productCount: products.length
      });
      return products;
    } catch (error) {
      this.logMethodError("updateOrderProduct", error);
      throw error;
    }
  }
  async removeProductFromOrder(identity) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
    this.logMethodStart("removeProductFromOrder", {
      product_id: identity.product_id,
      product_variant_id: identity.product_variant_id
    });
    try {
      if (!this.store.order)
        throw new Error("order 模块未初始化");
      const tempOrder = ((_b = (_a = this.store.order).getTempOrder) == null ? void 0 : _b.call(_a)) || ((_d = (_c = this.store.order).ensureTempOrder) == null ? void 0 : _d.call(_c));
      const products = await this.store.order.removeProductFromOrder(identity);
      if ((_e = tempOrder == null ? void 0 : tempOrder.bookings) == null ? void 0 : _e.length) {
        const venueProductUids = /* @__PURE__ */ new Set();
        const venueBookingUids = /* @__PURE__ */ new Set();
        for (const product of tempOrder.products || []) {
          if (!((_f = product == null ? void 0 : product.metadata) == null ? void 0 : _f.venue_booking))
            continue;
          if (product.identity_key)
            venueProductUids.add(String(product.identity_key));
          if ((_g = product.metadata) == null ? void 0 : _g.booking_uid) {
            venueBookingUids.add(String(product.metadata.booking_uid));
          }
        }
        const beforeBookingCount = ((_h = tempOrder.bookings) == null ? void 0 : _h.length) || 0;
        tempOrder.bookings = (tempOrder.bookings || []).filter((booking) => {
          var _a2, _b2;
          if (!((_a2 = booking == null ? void 0 : booking.metadata) == null ? void 0 : _a2.venue_booking))
            return true;
          if (booking.product_uid) {
            return venueProductUids.has(String(booking.product_uid));
          }
          const bookingUid = (_b2 = booking.metadata) == null ? void 0 : _b2.unique_identification_number;
          if (bookingUid)
            return venueBookingUids.has(String(bookingUid));
          return true;
        });
        if ((((_i = tempOrder.bookings) == null ? void 0 : _i.length) || 0) !== beforeBookingCount) {
          (_k = (_j = this.store.order).persistTempOrder) == null ? void 0 : _k.call(_j);
        }
      }
      await this.refreshItemRuleQuantityLimits();
      await this.refreshCartValidationPassed();
      this.logMethodSuccess("removeProductFromOrder", {
        productCount: products.length
      });
      return products;
    } catch (error) {
      this.logMethodError("removeProductFromOrder", error);
      throw error;
    }
  }
  async getProductList() {
    if (this.productsLoaded) {
      return (0, import_utils.attachItemRuleLimitsToTopLevelProducts)(
        this.getAddonProductsList(),
        this.store.itemRuleQuantityLimits || []
      );
    }
    const result = await this.loadAllProducts();
    return (0, import_utils.attachItemRuleLimitsToTopLevelProducts)(
      result.addonProducts,
      this.store.itemRuleQuantityLimits || []
    );
  }
  // ─── ItemRule 引擎 ───
  async loadOpenDataConfig() {
    if (!this.store.openData)
      throw new Error("openData 模块未初始化");
    const lastFetchedAt = this.store.openData.getLastFetchedAt();
    const cachedData = this.store.openData.getOpenData();
    if (cachedData && lastFetchedAt && Date.now() - lastFetchedAt < _VenueBookingImpl.OPEN_DATA_CACHE_TTL) {
      this.otherParams.openData = cachedData;
      return cachedData;
    }
    if (this.loadOpenDataConfigInFlight)
      return await this.loadOpenDataConfigInFlight;
    this.loadOpenDataConfigInFlight = this.store.openData.fetchOpenData({
      scope: "board",
      target: "venue_booking+online_store",
      section_code: [...OPEN_DATA_SECTION_CODES]
    });
    try {
      const openDataConfig = await this.loadOpenDataConfigInFlight;
      this.otherParams.openData = openDataConfig;
      return openDataConfig;
    } finally {
      this.loadOpenDataConfigInFlight = null;
    }
  }
  async loadRuntimeConfigs() {
    await this.loadOpenDataConfig();
    const itemRuleConfigs = await this.ensureItemRuleConfigsLoaded();
    this.logMethodSuccess("loadRuntimeConfigs", {
      itemRuleCount: itemRuleConfigs.length
    });
    return { itemRuleConfigs };
  }
  async fetchItemRuleConfigsByModelIds(strategyModelIds) {
    this.logMethodStart("fetchItemRuleConfigsByModelIds", { strategyModelIds });
    if (!strategyModelIds.length)
      return [];
    try {
      const result = await this.request.get("/promotion", {
        skip: 1,
        num: 99,
        status: "active",
        ids: strategyModelIds
      });
      let configs = [];
      if (result.code === 200) {
        configs = result.data.list.map((item) => item.metadata);
      }
      this.logMethodSuccess("fetchItemRuleConfigsByModelIds", {
        strategyModelIds,
        strategyCount: configs.length
      });
      return configs;
    } catch (error) {
      this.logMethodError("fetchItemRuleConfigsByModelIds", error, { strategyModelIds });
      return [];
    }
  }
  async buildPrefillProductSourceMap() {
    const sourceMap = /* @__PURE__ */ new Map();
    try {
      const productList = await this.getProductList();
      if (!Array.isArray(productList))
        return sourceMap;
      const visited = /* @__PURE__ */ new Set();
      const collectFromValue = (value) => {
        if (!value || typeof value !== "object")
          return;
        if (visited.has(value))
          return;
        visited.add(value);
        if (Array.isArray(value)) {
          for (const item of value)
            collectFromValue(item);
          return;
        }
        const node = value;
        const rawProductId = node.product_id ?? node.id;
        const productId = Number(rawProductId);
        if (Number.isFinite(productId) && productId > 0) {
          const productVariantId = Number(node.product_variant_id ?? node.variant_id ?? 0);
          const normalizedVariantId = Number.isNaN(productVariantId) ? 0 : productVariantId;
          const key = (0, import_utils.buildProductKey)(productId, normalizedVariantId);
          if (!sourceMap.has(key))
            sourceMap.set(key, node);
        }
        for (const childValue of Object.values(node)) {
          if (childValue && typeof childValue === "object")
            collectFromValue(childValue);
        }
      };
      collectFromValue(productList);
    } catch (error) {
      this.logMethodError("buildPrefillProductSourceMap", error);
    }
    return sourceMap;
  }
  getItemRuleRuntimeConfig() {
    return this.itemRuleRuntimeConfig || {};
  }
  async ensureItemRuleConfigsLoaded() {
    if (this.itemRuleConfigs.length > 0)
      return this.itemRuleConfigs;
    if (this.itemRuleConfigsPromise)
      return this.itemRuleConfigsPromise;
    this.itemRuleConfigsPromise = (async () => {
      const runtimeConfig = this.getItemRuleRuntimeConfig();
      const staticConfigs = (0, import_utils.normalizeItemRuleStrategies)(runtimeConfig.strategyConfigs);
      if (staticConfigs.length > 0) {
        this.itemRuleConfigs = staticConfigs;
        this.itemRuleEvaluator.setStrategyConfigs(staticConfigs);
        return this.itemRuleConfigs;
      }
      this.itemRuleConfigs = [];
      this.itemRuleEvaluator.setStrategyConfigs([]);
      return this.itemRuleConfigs;
    })();
    return await this.itemRuleConfigsPromise;
  }
  async refreshItemRuleQuantityLimits() {
    try {
      const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
      if (!strategyConfigs.length) {
        this.store.itemRuleQuantityLimits = [];
        return [];
      }
      const businessData = (0, import_utils.buildItemRuleBusinessData)({
        tempOrder: this.ensureTempOrder(),
        runtimeConfig: this.getItemRuleRuntimeConfig(),
        itemRuleConfigs: this.itemRuleConfigs
      });
      const limits = this.itemRuleEvaluator.getQuantityLimits(businessData);
      this.store.itemRuleQuantityLimits = limits;
      this.logMethodSuccess("refreshItemRuleQuantityLimits", { limitCount: limits.length });
      return limits;
    } catch (error) {
      this.store.itemRuleQuantityLimits = [];
      this.logMethodError("refreshItemRuleQuantityLimits", error);
      return [];
    }
  }
  async applyPrefillByItemRule() {
    var _a;
    if (this.itemRulePrefillApplied)
      return;
    if (!this.store.order)
      return;
    const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
    if (!strategyConfigs.length)
      return;
    const businessData = (0, import_utils.buildItemRuleBusinessData)({
      tempOrder: this.ensureTempOrder(),
      runtimeConfig: this.getItemRuleRuntimeConfig(),
      itemRuleConfigs: this.itemRuleConfigs
    });
    const prefillItems = this.itemRuleEvaluator.getPrefillItems(businessData);
    if (!prefillItems.length) {
      this.itemRulePrefillApplied = true;
      return;
    }
    const productSourceMap = await this.buildPrefillProductSourceMap();
    const tempOrder = this.ensureTempOrder();
    let hasChanges = false;
    for (const prefillItem of prefillItems) {
      const productId = Number(prefillItem.product_id);
      const productVariantId = Number(prefillItem.product_variant_id ?? 0);
      const targetQuantity = (0, import_utils.toNonNegativeInt)(prefillItem.quantity);
      if (!Number.isFinite(productId) || targetQuantity <= 0)
        continue;
      if (Number.isNaN(productVariantId))
        continue;
      const sourceItem = productSourceMap.get((0, import_utils.buildProductKey)(productId, productVariantId)) || productSourceMap.get((0, import_utils.buildProductKey)(productId, 0)) || null;
      const productIndex = (0, import_utils.getProductIdentityIndex)(tempOrder.products, {
        product_id: productId,
        product_variant_id: productVariantId
      });
      if (productIndex === -1) {
        const sellingPrice = (0, import_utils.toPriceString)((sourceItem == null ? void 0 : sourceItem.price) ?? (sourceItem == null ? void 0 : sourceItem.selling_price), "0.00");
        tempOrder.products.push(
          (0, import_utils.normalizeOrderProduct)({
            product_id: productId,
            product_variant_id: productVariantId,
            num: targetQuantity,
            selling_price: sellingPrice,
            original_price: sellingPrice,
            metadata: { item_rule_prefill: true, item_rule_id: prefillItem.ruleId },
            _origin: { ...sourceItem || {}, item_rule_prefill: true, item_rule_id: prefillItem.ruleId }
          })
        );
        hasChanges = true;
        continue;
      }
      const targetProduct = tempOrder.products[productIndex];
      const existedQuantity = (0, import_utils.toNonNegativeInt)(targetProduct.num);
      const delta = targetQuantity - existedQuantity;
      const nextProduct = {
        ...targetProduct,
        ...delta > 0 ? { num: (0, import_utils.getSafeProductNum)(existedQuantity + delta) } : {},
        metadata: { ...targetProduct.metadata || {}, item_rule_prefill: true, item_rule_id: prefillItem.ruleId },
        _origin: sourceItem ? { ...targetProduct._origin || {}, ...sourceItem } : targetProduct._origin
      };
      if (delta > 0 || Boolean(
        sourceItem && (!targetProduct._origin || ((_a = targetProduct._origin) == null ? void 0 : _a.price) !== (sourceItem == null ? void 0 : sourceItem.price))
      )) {
        tempOrder.products[productIndex] = nextProduct;
        hasChanges = true;
      }
    }
    if (hasChanges) {
      this.store.order.applyDiscount();
      await this.store.order.recalculateSummary({ createIfMissing: true });
      this.store.order.persistTempOrder();
    }
    await this.refreshItemRuleQuantityLimits();
    this.itemRulePrefillApplied = true;
    this.logMethodSuccess("applyPrefillByItemRule", {
      prefillCount: prefillItems.length,
      hasChanges
    });
  }
  async applyItemRulePrefill() {
    this.logMethodStart("applyItemRulePrefill");
    await this.applyPrefillByItemRule();
    await this.refreshItemRuleQuantityLimits();
    await this.refreshCartValidationPassed();
  }
  async evaluateCartValidationByItemRule() {
    const strategyConfigs = await this.ensureItemRuleConfigsLoaded();
    if (!strategyConfigs.length)
      return { passed: true, failures: [] };
    const businessData = (0, import_utils.buildItemRuleBusinessData)({
      tempOrder: this.ensureTempOrder(),
      runtimeConfig: this.getItemRuleRuntimeConfig(),
      itemRuleConfigs: this.itemRuleConfigs
    });
    return this.itemRuleEvaluator.validateCart(businessData);
  }
  async validateBeforeSubmitByItemRule() {
    const validationResult = await this.evaluateCartValidationByItemRule();
    if (validationResult.passed)
      return;
    const firstFailure = validationResult.failures[0];
    const errorMessage = (firstFailure == null ? void 0 : firstFailure.validationMessage) || "当前购物车未满足商品规则，请调整后再提交";
    const error = new Error(String(errorMessage));
    error.failures = validationResult.failures;
    throw error;
  }
  async refreshCartValidationPassed() {
    const previous = this.store.cartValidation || { passed: null, failures: [] };
    let nextState = {
      passed: null,
      failures: []
    };
    try {
      const validationResult = await this.evaluateCartValidationByItemRule();
      nextState = {
        passed: validationResult.passed,
        failures: validationResult.failures || []
      };
    } catch {
      nextState = { passed: false, failures: [] };
    }
    this.store.cartValidation = nextState;
    const changed = previous.passed !== nextState.passed || previous.failures !== nextState.failures;
    if (changed) {
      await this.core.effects.emit(import_types.VenueBookingHooks.onCartValidationChanged, {
        cartValidation: nextState,
        cartValidationPassed: nextState.passed
      });
    }
    return nextState.passed;
  }
  async setItemRuleRuntimeConfig(config = {}) {
    var _a, _b;
    this.logMethodStart("setItemRuleRuntimeConfig");
    this.itemRuleRuntimeConfig = {
      ...this.itemRuleRuntimeConfig,
      ...config,
      pax: { ...((_a = this.itemRuleRuntimeConfig) == null ? void 0 : _a.pax) || {}, ...(config == null ? void 0 : config.pax) || {} },
      custom: { ...((_b = this.itemRuleRuntimeConfig) == null ? void 0 : _b.custom) || {}, ...(config == null ? void 0 : config.custom) || {} }
    };
    if ("strategyConfigs" in config) {
      this.itemRuleConfigs = [];
      this.itemRuleConfigsPromise = null;
      this.itemRuleEvaluator.setStrategyConfigs([]);
    }
    this.itemRulePrefillApplied = false;
    await this.refreshItemRuleQuantityLimits();
    await this.refreshCartValidationPassed();
    this.logMethodSuccess("setItemRuleRuntimeConfig", {
      strategyCount: Array.isArray(this.itemRuleRuntimeConfig.strategyConfigs) ? this.itemRuleRuntimeConfig.strategyConfigs.length : 0
    });
  }
  getOtherParams() {
    return this.otherParams;
  }
  getUIStateBucketKey() {
    if (!this.cacheId)
      return null;
    return `${_VenueBookingImpl.UI_STATE_KEY_PREFIX}${this.cacheId}`;
  }
  readUIStateBucket() {
    var _a;
    const key = this.getUIStateBucketKey();
    if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
      return {};
    try {
      const raw = this.window.sessionStorage.getItem(key) || "{}";
      const parsed = JSON.parse(raw);
      return parsed && typeof parsed === "object" ? parsed : {};
    } catch {
      return {};
    }
  }
  writeUIStateBucket(bucket) {
    var _a;
    const key = this.getUIStateBucketKey();
    if (!key || !((_a = this.window) == null ? void 0 : _a.sessionStorage))
      return;
    this.window.sessionStorage.setItem(key, JSON.stringify(bucket));
  }
  setUIState(key, value) {
    if (!this.getUIStateBucketKey())
      return;
    const bucket = this.readUIStateBucket();
    bucket[key] = value;
    this.writeUIStateBucket(bucket);
  }
  getUIState(key) {
    if (!this.getUIStateBucketKey())
      return void 0;
    const bucket = this.readUIStateBucket();
    return bucket[key];
  }
  deleteUIState(key) {
    if (!this.getUIStateBucketKey())
      return;
    const bucket = this.readUIStateBucket();
    if (key in bucket) {
      delete bucket[key];
      this.writeUIStateBucket(bucket);
    }
  }
  // ─── OpenData 可用性 ───
  async checkOpenDataAvailability() {
    if (!this.store.openData)
      throw new Error("openData 模块未初始化");
    await this.loadOpenDataConfig();
    return this.store.openData.checkAvailability(this.store.schedule);
  }
  async setOtherParams(params, { cover = false } = {}) {
    if (cover) {
      this.otherParams = params;
    } else {
      this.otherParams = { ...this.otherParams, ...params };
    }
  }
};
var VenueBookingImpl = _VenueBookingImpl;
VenueBookingImpl.OPEN_DATA_CACHE_TTL = 5 * 60 * 1e3;
// ─── UI 状态缓存（按 cacheId 分桶，sessionStorage） ───
//
// 用于物料层持久化 UI 层面的轻量状态（如当前步骤、登录回跳意图等）。
// 桶键：pisell.venueBooking.uiState:<cacheId>；内部以 JSON object 形式存储多个字段。
// 无 cacheId 时所有方法自动降级为 no-op，上层不用判空。
VenueBookingImpl.UI_STATE_KEY_PREFIX = "pisell.venueBooking.uiState:";
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  VenueBookingImpl,
  ...require("./types")
});
