// classes.listcursor.ts

import * as plugins from './plugins.js';
import type { Bucket } from './classes.bucket.js';

export interface IListCursorOptions {
  pageSize?: number;
}

export interface IListCursorResult {
  keys: string[];
  done: boolean;
}

/**
 * ListCursor provides explicit pagination control for listing objects in a bucket.
 * Useful for UI pagination, resumable operations, and manual batch processing.
 */
export class ListCursor {
  private continuationToken?: string;
  private exhausted = false;
  private pageSize: number;

  constructor(
    private bucket: Bucket,
    private prefix: string,
    options: IListCursorOptions = {}
  ) {
    this.pageSize = options.pageSize || 1000;
  }

  /**
   * Fetch the next page of object keys
   * @returns Object with keys array and done flag
   */
  public async next(): Promise<IListCursorResult> {
    if (this.exhausted) {
      return { keys: [], done: true };
    }

    const command = new plugins.s3.ListObjectsV2Command({
      Bucket: this.bucket.name,
      Prefix: this.prefix,
      MaxKeys: this.pageSize,
      ContinuationToken: this.continuationToken,
    });

    const response = await this.bucket.smartbucketRef.storageClient.send(command);

    const keys = (response.Contents || [])
      .map((obj) => obj.Key)
      .filter((key): key is string => !!key);

    this.continuationToken = response.NextContinuationToken;
    this.exhausted = !this.continuationToken;

    return { keys, done: this.exhausted };
  }

  /**
   * Check if there are more pages to fetch
   */
  public hasMore(): boolean {
    return !this.exhausted;
  }

  /**
   * Reset the cursor to start from the beginning
   */
  public reset(): void {
    this.continuationToken = undefined;
    this.exhausted = false;
  }

  /**
   * Get the current continuation token (for saving/restoring state)
   */
  public getToken(): string | undefined {
    return this.continuationToken;
  }

  /**
   * Set the continuation token (for resuming from a saved state)
   */
  public setToken(token: string | undefined): void {
    this.continuationToken = token;
    this.exhausted = !token;
  }
}
