import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
class InMemoryColdStorageProvider {
  store = /* @__PURE__ */ new Map();
  async upload(key, data) {
    this.store.set(key, Buffer.from(data));
  }
  async download(key) {
    const data = this.store.get(key);
    return data ? Buffer.from(data) : null;
  }
  async exists(key) {
    return this.store.has(key);
  }
  async delete(key) {
    this.store.delete(key);
  }
  async list(prefix) {
    const keys = [];
    for (const key of this.store.keys()) {
      if (key.startsWith(prefix)) {
        keys.push(key);
      }
    }
    return keys;
  }
  /** Test helper: get current store size */
  get size() {
    return this.store.size;
  }
  /** Test helper: clear all stored data */
  clear() {
    this.store.clear();
  }
}
class StorageTierManager {
  provider = null;
  config;
  rehydrateCache = /* @__PURE__ */ new Map();
  constructor(config) {
    this.config = config;
  }
  async initialize() {
    switch (this.config.coldTierProvider) {
      case "s3":
        this.provider = await this.createS3Provider();
        break;
      case "gcs":
        this.provider = await this.createGCSProvider();
        break;
      default:
        this.provider = null;
    }
  }
  /**
   * Initialize with an externally-provided ColdStorageProvider.
   * Useful for testing or custom backends.
   */
  initializeWithProvider(provider) {
    this.provider = provider;
  }
  get isEnabled() {
    return this.provider !== null;
  }
  /** Archive a frame to cold storage */
  async archiveFrame(frame) {
    if (!this.provider) return false;
    const key = this.frameKey(frame.frame_id);
    const data = Buffer.from(JSON.stringify(frame));
    await this.provider.upload(key, data);
    return true;
  }
  /** Archive multiple frames (batch) */
  async archiveFrames(frames) {
    let archived = 0;
    for (const frame of frames) {
      if (await this.archiveFrame(frame)) archived++;
    }
    return archived;
  }
  /** Rehydrate a frame from cold storage (with local cache) */
  async rehydrateFrame(frameId) {
    const cached = this.rehydrateCache.get(frameId);
    const cacheMs = (this.config.rehydrateCacheMinutes ?? 30) * 60 * 1e3;
    if (cached && Date.now() - cached.cachedAt < cacheMs) {
      return cached.frame;
    }
    if (!this.provider) return null;
    const key = this.frameKey(frameId);
    const data = await this.provider.download(key);
    if (!data) return null;
    const frame = JSON.parse(data.toString());
    this.rehydrateCache.set(frameId, { frame, cachedAt: Date.now() });
    return frame;
  }
  /** Delete an archived frame from cold storage */
  async deleteArchived(frameId) {
    if (!this.provider) return false;
    const key = this.frameKey(frameId);
    const found = await this.provider.exists(key);
    if (!found) return false;
    await this.provider.delete(key);
    this.rehydrateCache.delete(frameId);
    return true;
  }
  /** Get storage stats */
  async getStats() {
    if (!this.provider) {
      return { provider: "none", archivedFrames: 0, bucket: "" };
    }
    const prefix = this.config.coldTierPrefix ?? "stackmemory/frames/";
    const keys = await this.provider.list(prefix);
    return {
      provider: this.config.coldTierProvider ?? "none",
      archivedFrames: keys.length,
      bucket: this.config.coldTierBucket ?? ""
    };
  }
  /** Clear the rehydration cache */
  clearCache() {
    this.rehydrateCache.clear();
  }
  frameKey(frameId) {
    const prefix = this.config.coldTierPrefix ?? "stackmemory/frames/";
    return `${prefix}${frameId}.json`;
  }
  async createS3Provider() {
    const {
      S3Client,
      PutObjectCommand,
      GetObjectCommand,
      HeadObjectCommand,
      DeleteObjectCommand,
      ListObjectsV2Command
    } = await import("@aws-sdk/client-s3");
    const client = new S3Client({});
    const bucket = this.config.coldTierBucket;
    return {
      async upload(key, data) {
        await client.send(
          new PutObjectCommand({ Bucket: bucket, Key: key, Body: data })
        );
      },
      async download(key) {
        try {
          const res = await client.send(
            new GetObjectCommand({ Bucket: bucket, Key: key })
          );
          const bytes = await res.Body?.transformToByteArray();
          return bytes ? Buffer.from(bytes) : null;
        } catch {
          return null;
        }
      },
      async exists(key) {
        try {
          await client.send(
            new HeadObjectCommand({ Bucket: bucket, Key: key })
          );
          return true;
        } catch {
          return false;
        }
      },
      async delete(key) {
        await client.send(
          new DeleteObjectCommand({ Bucket: bucket, Key: key })
        );
      },
      async list(prefix) {
        const res = await client.send(
          new ListObjectsV2Command({ Bucket: bucket, Prefix: prefix })
        );
        return (res.Contents ?? []).map((c) => c.Key).filter(Boolean);
      }
    };
  }
  async createGCSProvider() {
    const { Storage } = await import("@google-cloud/storage");
    const storage = new Storage();
    const bucket = storage.bucket(this.config.coldTierBucket);
    return {
      async upload(key, data) {
        await bucket.file(key).save(data);
      },
      async download(key) {
        try {
          const [data] = await bucket.file(key).download();
          return data;
        } catch {
          return null;
        }
      },
      async exists(key) {
        const [fileExists] = await bucket.file(key).exists();
        return fileExists;
      },
      async delete(key) {
        await bucket.file(key).delete();
      },
      async list(prefix) {
        const [files] = await bucket.getFiles({ prefix });
        return files.map((f) => f.name);
      }
    };
  }
}
export {
  InMemoryColdStorageProvider,
  StorageTierManager
};
//# sourceMappingURL=storage-tier-manager.js.map
