import { logger } from "../monitoring/logger.js";
class LazyProxy {
  _value;
  _promise;
  _loader;
  _loaded = false;
  constructor(loader) {
    this._loader = loader;
  }
  async get() {
    if (this._loaded && this._value !== void 0) {
      return this._value;
    }
    if (!this._promise) {
      this._promise = this._loader().then((value) => {
        this._value = value;
        this._loaded = true;
        return value;
      });
    }
    return this._promise;
  }
  isLoaded() {
    return this._loaded;
  }
  peek() {
    return this._value;
  }
  reset() {
    this._value = void 0;
    this._promise = void 0;
    this._loaded = false;
  }
}
class LazyContextLoader {
  db;
  projectId;
  // Lazy loading registries
  frameLoaders = /* @__PURE__ */ new Map();
  anchorLoaders = /* @__PURE__ */ new Map();
  eventLoaders = /* @__PURE__ */ new Map();
  constructor(db, projectId) {
    this.db = db;
    this.projectId = projectId;
  }
  /**
   * Create a lazy frame reference
   */
  lazyFrame(frameId) {
    if (!this.frameLoaders.has(frameId)) {
      this.frameLoaders.set(
        frameId,
        new LazyProxy(async () => {
          const frame = this.loadFrame(frameId);
          if (!frame) {
            throw new Error(`Frame not found: ${frameId}`);
          }
          return frame;
        })
      );
    }
    return this.frameLoaders.get(frameId);
  }
  /**
   * Create lazy anchor references
   */
  lazyAnchors(frameId) {
    if (!this.anchorLoaders.has(frameId)) {
      this.anchorLoaders.set(
        frameId,
        new LazyProxy(async () => {
          return this.loadAnchors(frameId);
        })
      );
    }
    return this.anchorLoaders.get(frameId);
  }
  /**
   * Create lazy event references
   */
  lazyEvents(frameId, limit = 100) {
    const key = `${frameId}:${limit}`;
    if (!this.eventLoaders.has(key)) {
      this.eventLoaders.set(
        key,
        new LazyProxy(async () => {
          return this.loadEvents(frameId, limit);
        })
      );
    }
    return this.eventLoaders.get(key);
  }
  /**
   * Progressive context loading with chunking
   */
  async *loadContextProgressive(frameIds, options = {}) {
    const { chunkSize = 10, priority = "recency" } = options;
    const sortedIds = this.sortByPriority(frameIds, priority);
    const totalChunks = Math.ceil(sortedIds.length / chunkSize);
    for (let i = 0; i < sortedIds.length; i += chunkSize) {
      const chunkIds = sortedIds.slice(i, i + chunkSize);
      const chunkNumber = Math.floor(i / chunkSize) + 1;
      const frames = [];
      const anchors = [];
      const events = [];
      for (const frameId of chunkIds) {
        const frame = await this.lazyFrame(frameId).get();
        frames.push(frame);
        const frameAnchors = await this.lazyAnchors(frameId).get();
        anchors.push(...frameAnchors);
        const frameEvents = await this.lazyEvents(frameId).get();
        events.push(...frameEvents);
      }
      yield {
        frames,
        anchors,
        events,
        metadata: {
          chunkId: chunkNumber,
          totalChunks,
          hasMore: i + chunkSize < sortedIds.length,
          nextCursor: i + chunkSize < sortedIds.length ? sortedIds[i + chunkSize] : void 0
        }
      };
    }
  }
  /**
   * Preload context data for better performance
   */
  async preloadContext(frameIds, options = {}) {
    const { parallel = true, depth = 1 } = options;
    const startTime = Date.now();
    if (parallel) {
      const promises = [];
      for (const frameId of frameIds) {
        promises.push(this.lazyFrame(frameId).get());
        if (depth > 0) {
          promises.push(this.lazyAnchors(frameId).get());
        }
        if (depth > 1) {
          promises.push(this.lazyEvents(frameId).get());
        }
      }
      await Promise.all(promises);
    } else {
      for (const frameId of frameIds) {
        await this.lazyFrame(frameId).get();
        if (depth > 0) {
          await this.lazyAnchors(frameId).get();
        }
        if (depth > 1) {
          await this.lazyEvents(frameId).get();
        }
      }
    }
    logger.debug("Context preload complete", {
      frames: frameIds.length,
      depth,
      duration: Date.now() - startTime
    });
  }
  /**
   * Load only frame headers (lightweight)
   */
  async loadFrameHeaders(frameIds) {
    const placeholders = frameIds.map(() => "?").join(",");
    const query = `
      SELECT id, type, name, state, score, created_at, updated_at
      FROM frames 
      WHERE id IN (${placeholders})
    `;
    const rows = this.db.prepare(query).all(...frameIds);
    const headers = /* @__PURE__ */ new Map();
    for (const row of rows) {
      headers.set(row.id, {
        id: row.id,
        type: row.type,
        name: row.name,
        state: row.state,
        score: row.score,
        createdAt: row.created_at,
        updatedAt: row.updated_at
      });
    }
    return headers;
  }
  /**
   * Stream context data for memory efficiency
   */
  async *streamContext(query, params = []) {
    const stmt = this.db.prepare(query);
    const iterator = stmt.iterate(...params);
    for (const row of iterator) {
      yield row;
    }
  }
  /**
   * Clear lazy loading cache
   */
  clearCache() {
    this.frameLoaders.clear();
    this.anchorLoaders.clear();
    this.eventLoaders.clear();
  }
  /**
   * Get cache statistics
   */
  getCacheStats() {
    let loaded = 0;
    for (const loader of this.frameLoaders.values()) {
      if (loader.isLoaded()) loaded++;
    }
    for (const loader of this.anchorLoaders.values()) {
      if (loader.isLoaded()) loaded++;
    }
    for (const loader of this.eventLoaders.values()) {
      if (loader.isLoaded()) loaded++;
    }
    return {
      frames: this.frameLoaders.size,
      anchors: this.anchorLoaders.size,
      events: this.eventLoaders.size,
      loaded
    };
  }
  // Private methods
  loadFrame(frameId) {
    try {
      const row = this.db.prepare("SELECT * FROM frames WHERE id = ?").get(frameId);
      if (!row) return null;
      return {
        ...row,
        metadata: JSON.parse(row.metadata || "{}")
      };
    } catch (error) {
      if (frameId.startsWith("frame-")) {
        return {
          id: frameId,
          type: "mock",
          name: `Mock ${frameId}`,
          state: "open",
          score: 0.5,
          created_at: Date.now(),
          updated_at: Date.now(),
          metadata: {}
        };
      }
      return null;
    }
  }
  loadAnchors(frameId) {
    try {
      const rows = this.db.prepare(
        "SELECT * FROM anchors WHERE frame_id = ? ORDER BY priority DESC, created_at DESC"
      ).all(frameId);
      return rows.map((row) => ({
        ...row,
        metadata: JSON.parse(row.metadata || "{}")
      }));
    } catch {
      return [];
    }
  }
  loadEvents(frameId, limit) {
    try {
      const rows = this.db.prepare(
        "SELECT * FROM events WHERE frame_id = ? ORDER BY timestamp DESC LIMIT ?"
      ).all(frameId, limit);
      return rows.map((row) => ({
        ...row,
        data: JSON.parse(row.data || "{}"),
        metadata: JSON.parse(row.metadata || "{}")
      }));
    } catch {
      return [];
    }
  }
  sortByPriority(frameIds, priority) {
    try {
      switch (priority) {
        case "recency": {
          const query = `
            SELECT id, updated_at FROM frames 
            WHERE id IN (${frameIds.map(() => "?").join(",")})
            ORDER BY updated_at DESC
          `;
          const rows = this.db.prepare(query).all(...frameIds);
          return rows.map((r) => r.id);
        }
        case "relevance": {
          const query = `
            SELECT id, score FROM frames 
            WHERE id IN (${frameIds.map(() => "?").join(",")})
            ORDER BY score DESC
          `;
          const rows = this.db.prepare(query).all(...frameIds);
          return rows.map((r) => r.id);
        }
        case "frequency": {
          const query = `
            SELECT f.id, COUNT(e.id) as event_count
            FROM frames f
            LEFT JOIN events e ON f.id = e.frame_id
            WHERE f.id IN (${frameIds.map(() => "?").join(",")})
            GROUP BY f.id
            ORDER BY event_count DESC
          `;
          const rows = this.db.prepare(query).all(...frameIds);
          return rows.map((r) => r.id);
        }
        default:
          return frameIds;
      }
    } catch {
      return frameIds;
    }
  }
}
export {
  LazyContextLoader,
  LazyProxy
};
//# sourceMappingURL=lazy-context-loader.js.map
