import type { Page } from "playwright";

/** Options for pw_wait_predicate. */
export interface PwWaitOptions {
  /** Maximum time to wait in milliseconds. Default: 5000 */
  timeoutMs?: number;
  /** Polling interval in milliseconds. Default: 100 */
  pollMs?: number;
  /** Argument passed to the predicate function in the page context. */
  arg?: unknown;
  /** Custom error message prepended to the timeout error. */
  message?: string;
}

/**
 * pw_wait_predicate — polls an arbitrary predicate inside the page context
 * until it returns truthy or the timeout elapses.
 *
 * Thin wrapper around `page.waitForFunction` with friendlier defaults and
 * optional custom error messages. More flexible than `waitForSelector` for
 * computed conditions such as "card has class .border-red" or "exactly 1
 * element is highlighted".
 */
export async function pw_wait_predicate<T = unknown>(
  page: Page,
  predicate: string | ((arg?: unknown) => unknown),
  opts: PwWaitOptions = {},
): Promise<T> {
  const timeoutMs = opts.timeoutMs ?? 5000;
  const pollMs = opts.pollMs ?? 100;

  try {
    const handle = await page.waitForFunction(predicate, opts.arg, {
      timeout: timeoutMs,
      polling: pollMs,
    });
    return handle.jsonValue() as Promise<T>;
  } catch (err) {
    if (opts.message) {
      const cause = err instanceof Error ? err : new Error(String(err));
      throw new Error(`${opts.message}: ${cause.message}`, { cause });
    }
    throw err;
  }
}
