import { computeStaggerMs, humanPause } from "@/lib/threads-browser/human-behavior";

/** 有限平行執行，批次間加隨機間隔以降低被封風險 */
export async function runWithConcurrency<T, R>(
  items: T[],
  worker: (item: T, index: number) => Promise<R>,
  options?: {
    concurrency?: number;
    staggerMs?: [number, number];
    onProgress?: (done: number, total: number) => void;
    shouldAbort?: () => boolean | Promise<boolean>;
  }
): Promise<R[]> {
  const concurrency = Math.max(1, options?.concurrency ?? 1);
  const stagger = options?.staggerMs ?? [3500, 9000];
  const results: R[] = new Array(items.length);
  let nextIndex = 0;
  let done = 0;

  async function runWorker() {
    while (true) {
      if (await options?.shouldAbort?.()) {
        throw new Error("__JOB_ABORT__");
      }
      const index = nextIndex++;
      if (index >= items.length) return;
      if (index > 0) {
        await new Promise((resolve) => setTimeout(resolve, computeStaggerMs(stagger)));
        if (Math.random() < 0.15 + Math.random() * 0.18) {
          await humanPause(Math.random() < 0.55 ? "short" : "medium");
        }
      }
      if (await options?.shouldAbort?.()) {
        throw new Error("__JOB_ABORT__");
      }
      results[index] = await worker(items[index], index);
      done++;
      options?.onProgress?.(done, items.length);
    }
  }

  const workers = Array.from({ length: Math.min(concurrency, items.length) }, () =>
    runWorker()
  );
  await Promise.all(workers);
  return results;
}