// src/tests/utils/poll.ts

interface PollOptions {
  /** The maximum time to wait in milliseconds. Defaults to 10000 (10 seconds). */
  timeout?: number;
  /** The interval between attempts in milliseconds. Defaults to 500. */
  interval?: number;
  /** A description of the operation for better error messages. */
  description?: string;
}

/**
 * A generic polling utility for asynchronous operations in tests.
 *
 * @param fn The async function to execute on each attempt.
 * @param validate A function that returns `true` if the result is satisfactory, ending the poll.
 * @param options Polling options like timeout and interval.
 * @returns A promise that resolves with the first valid result from `fn`.
 * @throws An error if the timeout is reached before `validate` returns `true`.
 */
export async function poll<T>(
  fn: () => Promise<T>,
  validate: (result: T) => boolean,
  options: PollOptions = {},
): Promise<T> {
  const { timeout = 10000, interval = 500, description = 'operation' } = options;
  const startTime = Date.now();

  while (Date.now() - startTime < timeout) {
    const result = await fn();
    if (validate(result)) return result;
    await new Promise((resolve) => setTimeout(resolve, interval));
  }

  throw new Error(`Polling timed out for ${description} after ${timeout}ms.`);
}