type Task<T> = () => Promise<T>;
type ProgressCallback = (completed: number, total: number) => void;

class PromisePool<T = any> {
  private concurrency: number;
  private tasks: Task<T>[];
  private results: T[] = [];
  private errors: Error[] = [];

  constructor(concurrency: number = 3) {
    this.concurrency = concurrency;
    this.tasks = [];
  }

  add(task: Task<T>): this {
    this.tasks.push(task);
    return this;
  }

  async execute(onProgress?: ProgressCallback): Promise<{ results: T[]; errors: Error[] }> {
    this.results = [];
    this.errors = [];
    
    const executing: Promise<void>[] = [];
    let completed = 0;
    
    for (const task of this.tasks) {
      const promise = task()
        .then(result => {
          this.results.push(result);
          completed++;
          onProgress?.(completed, this.tasks.length);
        })
        .catch(error => {
          this.errors.push(error instanceof Error ? error : new Error(String(error)));
          completed++;
          onProgress?.(completed, this.tasks.length);
        })
        .finally(() => {
          executing.splice(executing.indexOf(promise), 1);
        });
      
      executing.push(promise);
      
      if (executing.length >= this.concurrency) {
        await Promise.race(executing);
      }
    }
    
    await Promise.all(executing);
    
    return { results: this.results, errors: this.errors };
  }
}

export default PromisePool;