var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/server/modules/resource/index.ts
var resource_exports = {};
__export(resource_exports, {
  ResourceHooks: () => import_types2.ResourceHooks,
  ResourceModule: () => ResourceModule,
  resourceModule: () => resourceModule
});
module.exports = __toCommonJS(resource_exports);
var import_lodash_es = require("lodash-es");
var import_BaseModule = require("../../../modules/BaseModule");
var import_types = require("./types");
var import_types2 = require("./types");
var RESOURCE_STORE_NAME = "resources";
var DEFAULT_PAGE_SIZE = 999;
var RESOURCE_SYNC_DEBOUNCE_MS = 1e4;
var ResourceModule = class extends import_BaseModule.BaseModule {
  constructor(name, version) {
    super(name, version);
    this.defaultName = "resource";
    this.defaultVersion = "1.0.0";
    /** 倒排索引: resourceId -> ResourceBooking[] */
    this.resourceIdIndex = /* @__PURE__ */ new Map();
    /** 待处理的同步消息队列 */
    this.pendingSyncMessages = [];
  }
  // ─────────────────────────────────────────────────────────────────
  // 初始化 & 生命周期
  // ─────────────────────────────────────────────────────────────────
  async initialize(core, options) {
    var _a, _b;
    this.core = core;
    this.store = options == null ? void 0 : options.store;
    if (Array.isArray((_a = options == null ? void 0 : options.initialState) == null ? void 0 : _a.list)) {
      this.store.list = ((_b = options == null ? void 0 : options.initialState) == null ? void 0 : _b.list).map(
        (item) => this.normalizeResource(item)
      );
      this.syncResourcesMap();
      this.core.effects.emit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
    } else {
      this.store.list = [];
      this.store.map = /* @__PURE__ */ new Map();
    }
    if (!Array.isArray(this.store.bookings)) {
      this.store.bookings = [];
    }
    const appPlugin = core.getPlugin("app");
    if (appPlugin) {
      const app = appPlugin.getApp();
      this.dbManager = app.sqlite || app.dbManager;
      this.logger = app.logger;
    }
    this.initResourceDataSource();
  }
  logInfo(title, metadata) {
    if (this.logger) {
      this.logger.addLog({
        type: "info",
        title: `[ResourceModule] ${title}`,
        metadata: metadata || {}
      });
    }
  }
  logError(title, error, metadata) {
    if (this.logger) {
      this.logger.addLog({
        type: "error",
        title: `[ResourceModule] ${title}`,
        metadata: metadata || {}
      });
    }
  }
  async preload() {
    await this.setupResourceSync();
    const cachedResources = await this.loadResourcesFromSQLite();
    if (cachedResources.length > 0) {
      this.store.list = (0, import_lodash_es.cloneDeep)(cachedResources).map((item) => this.normalizeResource(item));
      this.syncResourcesMap();
      await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
    } else {
      const resources = await this.loadResourcesByServer();
      if (resources.length > 0) {
        this.store.list = (0, import_lodash_es.cloneDeep)(resources).map((item) => this.normalizeResource(item));
        this.syncResourcesMap();
        await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
      }
    }
  }
  getRoutes() {
    return [];
  }
  destroy() {
    var _a;
    if (this.syncTimer) {
      clearTimeout(this.syncTimer);
      this.syncTimer = void 0;
    }
    this.pendingSyncMessages = [];
    if ((_a = this.resourceDataSource) == null ? void 0 : _a.destroy)
      this.resourceDataSource.destroy();
    super.destroy();
  }
  // ─────────────────────────────────────────────────────────────────
  // Resource CRUD
  // ─────────────────────────────────────────────────────────────────
  /**
   * 获取所有资源（支持 includeBookings 附加预订信息）
   */
  getResources(queryOptions) {
    this.logInfo("getResources", {
      queryOptions
    });
    if (!(queryOptions == null ? void 0 : queryOptions.includeBookings)) {
      return this.store.list;
    }
    return this.store.list.map((resource) => this.attachBookingsToResource(resource));
  }
  /**
   * 根据 ID 获取单个资源
   */
  getResourceById(id, queryOptions) {
    const resource = this.store.map.get(id);
    if (!resource)
      return void 0;
    if (queryOptions == null ? void 0 : queryOptions.includeBookings) {
      return this.attachBookingsToResource(resource);
    }
    return resource;
  }
  /**
   * 创建资源
   */
  createResource(data) {
    const id = (data == null ? void 0 : data.id) ?? (data == null ? void 0 : data.form_record_id) ?? Date.now();
    const resource = this.normalizeResource({ ...data, id });
    this.store.list.push(resource);
    this.store.map.set(resource.id, resource);
    this.saveResourcesToSQLite(this.store.list).catch(() => {
    });
    this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
    return resource;
  }
  /**
   * 更新资源
   */
  updateResource(id, data) {
    const index = this.store.list.findIndex((r) => this.getIdKey(r.id) === this.getIdKey(id));
    if (index === -1)
      return void 0;
    const updated = this.normalizeResource({ ...this.store.list[index], ...data, id });
    this.store.list[index] = updated;
    this.store.map.set(updated.id, updated);
    this.saveResourcesToSQLite(this.store.list).catch(() => {
    });
    this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
    return updated;
  }
  /**
   * 删除资源
   */
  deleteResource(id) {
    const key = this.getIdKey(id);
    const index = this.store.list.findIndex((r) => this.getIdKey(r.id) === key);
    if (index === -1)
      return false;
    this.store.list.splice(index, 1);
    this.store.map.delete(id);
    this.saveResourcesToSQLite(this.store.list).catch(() => {
    });
    this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
    return true;
  }
  // ─────────────────────────────────────────────────────────────────
  // Booking CRUD
  // ─────────────────────────────────────────────────────────────────
  /**
   * 根据资源 ID 获取预订列表
   */
  getBookingsByResourceId(resourceId) {
    return this.resourceIdIndex.get(resourceId) || [];
  }
  /**
   * 创建预订
   */
  // createBooking(booking: Partial<ResourceBooking>): ResourceBooking {
  //   const id = booking?.id ?? Date.now()
  //   const normalized: ResourceBooking = {
  //     id,
  //     ...booking,
  //   } as ResourceBooking
  //   this.store.bookings.push(normalized)
  //   const rid = normalized.resource_id ?? normalized.resourceId
  //   if (rid !== undefined) {
  //     const existing = this.resourceIdIndex.get(rid) || []
  //     existing.push(normalized)
  //     this.resourceIdIndex.set(rid, existing)
  //   }
  //   this.saveBookingsToSQLite(this.store.bookings).catch(() => {})
  //   this.safeEmit(ResourceHooks.onBookingsChanged, this.store.bookings)
  //   return normalized
  // }
  /**
   * 更新预订
   */
  // updateBooking(id: ResourceId, data: Partial<ResourceBooking>): ResourceBooking | undefined {
  //   const index = this.store.bookings.findIndex(b => this.getIdKey(b.id) === this.getIdKey(id))
  //   if (index === -1) return undefined
  //   const old = this.store.bookings[index]
  //   const updated: ResourceBooking = { ...old, ...data, id: old.id } as ResourceBooking
  //   this.store.bookings[index] = updated
  //   this.rebuildBookingsIndex()
  //   this.saveBookingsToSQLite(this.store.bookings).catch(() => {})
  //   this.safeEmit(ResourceHooks.onBookingsChanged, this.store.bookings)
  //   return updated
  // }
  /**
   * 删除预订
   */
  // deleteBooking(id: ResourceId): boolean {
  //   const index = this.store.bookings.findIndex(b => this.getIdKey(b.id) === this.getIdKey(id))
  //   if (index === -1) return false
  //   this.store.bookings.splice(index, 1)
  //   this.rebuildBookingsIndex()
  //   this.saveBookingsToSQLite(this.store.bookings).catch(() => {})
  //   this.safeEmit(ResourceHooks.onBookingsChanged, this.store.bookings)
  //   return true
  // }
  /**
   * 清空缓存
   */
  async clear() {
    this.store.list = [];
    this.store.map.clear();
    this.store.bookings = [];
    this.resourceIdIndex.clear();
    if (this.dbManager) {
      try {
        await this.dbManager.clear(RESOURCE_STORE_NAME);
      } catch {
      }
    }
    await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
    await this.safeEmit(import_types.ResourceHooks.onBookingsChanged, this.store.bookings);
  }
  // ─────────────────────────────────────────────────────────────────
  // 内部工具方法
  // ─────────────────────────────────────────────────────────────────
  attachBookingsToResource(resource) {
    return {
      ...resource,
      bookings: this.getBookingsByResourceId(resource.id)
    };
  }
  normalizeResource(resource) {
    const normalized = {
      ...resource,
      id: (resource == null ? void 0 : resource.id) ?? (resource == null ? void 0 : resource.form_record_id) ?? ""
    };
    if (normalized.form_record_id === void 0 && normalized.id !== "") {
      normalized.form_record_id = normalized.id;
    }
    if (normalized.resource_form_id === void 0 || normalized.resource_form_id === null) {
      normalized.resource_form_id = "";
    }
    if (normalized.schedule === void 0 || normalized.schedule === null) {
      normalized.schedule = "";
    }
    if (Array.isArray(normalized.times)) {
      normalized.times = normalized.times.map((timeSlot) => {
        if (!timeSlot || typeof timeSlot !== "object")
          return timeSlot;
        const startAt = timeSlot.start_at ?? timeSlot.start;
        const endAt = timeSlot.end_at ?? timeSlot.end;
        return {
          ...timeSlot,
          start_at: startAt,
          end_at: endAt,
          start: timeSlot.start ?? startAt,
          end: timeSlot.end ?? endAt
        };
      });
    }
    if (Array.isArray(normalized.children)) {
      normalized.children = normalized.children.map((child) => this.normalizeResource(child));
    }
    return normalized;
  }
  async safeEmit(event, payload) {
    try {
      await this.core.effects.emit(event, payload);
    } catch (error) {
      console.error(`[ResourceModule] 事件派发失败: ${event}`, error);
    }
  }
  syncResourcesMap() {
    this.store.map = /* @__PURE__ */ new Map();
    for (const resource of this.store.list) {
      this.store.map.set(resource.id, resource);
    }
  }
  syncBookingsIndex() {
    this.resourceIdIndex.clear();
    for (const booking of this.store.bookings) {
      const rid = booking.resource_id ?? booking.resourceId;
      if (rid === void 0)
        continue;
      const existing = this.resourceIdIndex.get(rid) || [];
      existing.push(booking);
      this.resourceIdIndex.set(rid, existing);
    }
  }
  rebuildBookingsIndex() {
    this.syncBookingsIndex();
  }
  getIdKey(id) {
    return String(id);
  }
  // ─────────────────────────────────────────────────────────────────
  // 数据加载
  // ─────────────────────────────────────────────────────────────────
  async loadResourcesByServer() {
    if (!this.resourceDataSource)
      return [];
    try {
      const response = await this.resourceDataSource.getResourcePage({
        num: DEFAULT_PAGE_SIZE,
        skip: 1
      });
      const resourceList = Array.isArray(response == null ? void 0 : response.list) ? response.list : [];
      const normalizedList = resourceList.map((item) => this.normalizeResource(item));
      await this.saveResourcesToSQLite(normalizedList);
      await this.safeEmit(import_types.ResourceHooks.onResourcesLoaded, normalizedList);
      return normalizedList;
    } catch {
      return [];
    }
  }
  // ─────────────────────────────────────────────────────────────────
  // SQLite 持久化
  // ─────────────────────────────────────────────────────────────────
  async loadResourcesFromSQLite() {
    if (!this.dbManager)
      return [];
    try {
      const resources = await this.dbManager.getAll(RESOURCE_STORE_NAME);
      return resources || [];
    } catch {
      return [];
    }
  }
  async saveResourcesToSQLite(resourceList) {
    if (!this.dbManager)
      return;
    try {
      await this.dbManager.clear(RESOURCE_STORE_NAME);
      if (resourceList.length === 0)
        return;
      if (this.dbManager.bulkAdd) {
        await this.dbManager.bulkAdd(RESOURCE_STORE_NAME, resourceList);
        return;
      }
      await Promise.all(resourceList.map((r) => this.dbManager.add(RESOURCE_STORE_NAME, r)));
    } catch (error) {
      console.error("saveResourcesToSQLite error", error);
      this.logError("保存资源到 SQLite 失败", {
        error: error instanceof Error ? error.message : String(error),
        resourceList: resourceList.length
      });
    }
  }
  // private async loadBookingsFromSQLite(): Promise<ResourceBooking[]> {
  //   if (!this.dbManager) return []
  //   try {
  //     const bookings = await this.dbManager.getAll(BOOKING_STORE_NAME)
  //     return bookings || []
  //   } catch {
  //     return []
  //   }
  // }
  // private async saveBookingsToSQLite(bookings: ResourceBooking[]): Promise<void> {
  //   if (!this.dbManager) return
  //   try {
  //     await this.dbManager.clear(BOOKING_STORE_NAME)
  //     if (bookings.length === 0) return
  //     if (this.dbManager.bulkAdd) {
  //       await this.dbManager.bulkAdd(BOOKING_STORE_NAME, bookings)
  //       return
  //     }
  //     await Promise.all(bookings.map(b => this.dbManager.add(BOOKING_STORE_NAME, b)))
  //   } catch {
  //     // 忽略 SQLite 异常
  //   }
  // }
  // ─────────────────────────────────────────────────────────────────
  // pubsub 同步
  // ─────────────────────────────────────────────────────────────────
  initResourceDataSource() {
    var _a, _b;
    const ResourceDataSourceClass = (_b = (_a = this.core.serverOptions) == null ? void 0 : _a.All_DATA_SOURCES) == null ? void 0 : _b.ResourceDataSource;
    if (!ResourceDataSourceClass)
      return;
    this.resourceDataSource = new ResourceDataSourceClass();
  }
  async setupResourceSync() {
    var _a, _b, _c;
    if (!this.resourceDataSource)
      return;
    const result = await this.resourceDataSource.run({
      pubsub: {
        callback: (res) => {
          const data = (res == null ? void 0 : res.data) || res;
          if (!data)
            return;
          const channelKey = data.module || "resource";
          this.pendingSyncMessages.push({ ...data, _channelKey: channelKey });
          if (this.syncTimer)
            clearTimeout(this.syncTimer);
          this.syncTimer = setTimeout(() => {
            this.processSyncMessages();
          }, RESOURCE_SYNC_DEBOUNCE_MS);
        }
      }
    }).catch(() => {
    });
    console.log("result", result);
    this.logInfo("setupResourceSync: 资源列表查询结果", { result });
    if ((_b = (_a = result == null ? void 0 : result.data) == null ? void 0 : _a.list) == null ? void 0 : _b.length) {
      await this.mergeResourcesToStore((_c = result == null ? void 0 : result.data) == null ? void 0 : _c.list);
    }
  }
  async processSyncMessages() {
    var _a, _b, _c;
    const messages = [...this.pendingSyncMessages];
    this.pendingSyncMessages = [];
    if (messages.length === 0)
      return;
    const deleteIds = [];
    const bodyUpdates = /* @__PURE__ */ new Map();
    const sseRefreshIds = [];
    for (const msg of messages) {
      if (msg.operation === "delete" || msg.action === "delete") {
        if ((_a = msg.ids) == null ? void 0 : _a.length)
          deleteIds.push(...msg.ids);
        else if (msg.id !== void 0)
          deleteIds.push(msg.id);
        continue;
      }
      if (msg.body) {
        const bodyId = msg.body.id ?? msg.id;
        if (bodyId === void 0)
          continue;
        bodyUpdates.set(this.getIdKey(bodyId), { ...msg.body, id: bodyId });
        continue;
      }
      if ((_b = msg.ids) == null ? void 0 : _b.length) {
        sseRefreshIds.push(...msg.ids);
      } else if (msg.id !== void 0) {
        sseRefreshIds.push(msg.id);
      } else if ((_c = msg.relation_resource_ids) == null ? void 0 : _c.length) {
        sseRefreshIds.push(...msg.relation_resource_ids);
      }
    }
    const uniqueDeleteIds = this.uniqueResourceIds(deleteIds);
    const uniqueSSEIds = this.uniqueResourceIds(sseRefreshIds);
    const bodyList = [...bodyUpdates.values()];
    if (uniqueDeleteIds.length > 0)
      await this.removeResourcesByIds(uniqueDeleteIds);
    if (bodyList.length > 0)
      await this.mergeResourcesToStore(bodyList);
    if (uniqueSSEIds.length > 0) {
      const freshResources = await this.fetchResourcesBySSE(uniqueSSEIds);
      if (freshResources.length > 0)
        await this.mergeResourcesToStore(freshResources);
    }
    if (uniqueDeleteIds.length === 0 && bodyList.length === 0 && uniqueSSEIds.length === 0)
      return;
    await this.core.effects.emit(import_types.ResourceHooks.onResourcesSyncCompleted, null);
  }
  async fetchResourcesBySSE(ids) {
    if (!this.resourceDataSource)
      return [];
    try {
      const list = await this.resourceDataSource.run({
        sse: { query: { type: "resource", ids } }
      });
      return list || [];
    } catch {
      return [];
    }
  }
  async removeResourcesByIds(ids) {
    const keySet = new Set(ids.map((id) => this.getIdKey(id)));
    this.store.list = this.store.list.filter((r) => !keySet.has(this.getIdKey(r.id)));
    this.syncResourcesMap();
    if (this.dbManager) {
      try {
        for (const id of ids) {
          await this.dbManager.delete(RESOURCE_STORE_NAME, id);
        }
      } catch {
      }
    }
    await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
  }
  async mergeResourcesToStore(freshResources) {
    const freshMap = /* @__PURE__ */ new Map();
    for (const r of freshResources) {
      if ((r == null ? void 0 : r.id) === void 0)
        continue;
      freshMap.set(this.getIdKey(r.id), this.normalizeResource(r));
    }
    const updatedList = this.store.list.map((r) => {
      const key = this.getIdKey(r.id);
      if (!freshMap.has(key))
        return r;
      const fresh = freshMap.get(key);
      freshMap.delete(key);
      return fresh;
    });
    for (const r of freshMap.values()) {
      updatedList.push(r);
    }
    this.store.list = updatedList;
    this.syncResourcesMap();
    await this.saveResourcesToSQLite(this.store.list);
    await this.safeEmit(import_types.ResourceHooks.onResourcesChanged, this.store.list);
  }
  uniqueResourceIds(ids) {
    const idMap = /* @__PURE__ */ new Map();
    for (const id of ids) {
      idMap.set(this.getIdKey(id), id);
    }
    return [...idMap.values()];
  }
};
var resourceModule = new ResourceModule();
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  ResourceHooks,
  ResourceModule,
  resourceModule
});
