'use strict';

class SerialTaskQueue {
  constructor(name = 'serial-task-queue') {
    this.name = name;
    this._tail = Promise.resolve();
    this._active = null;
    this._pending = 0;
  }

  run(label, fn) {
    if (typeof fn !== 'function') throw new TypeError('SerialTaskQueue.run requires a function');
    const taskLabel = label || 'task';
    this._pending += 1;
    const runTask = async () => {
      this._pending -= 1;
      this._active = taskLabel;
      try {
        return await fn();
      } finally {
        this._active = null;
      }
    };
    const job = this._tail.then(runTask, runTask);
    this._tail = job.catch(() => {});
    return job;
  }

  async drain(timeoutMs = 5000) {
    const timeout = Math.max(0, Number(timeoutMs) || 0);
    if (timeout === 0) {
      await this._tail;
      return { ok: true, timedOut: false };
    }
    let timer = null;
    try {
      return await Promise.race([
        this._tail.then(() => ({ ok: true, timedOut: false })),
        new Promise((resolve) => {
          timer = setTimeout(() => resolve({
            ok: false,
            timedOut: true,
            active: this._active,
            pending: this._pending,
          }), timeout);
          if (typeof timer.unref === 'function') timer.unref();
        }),
      ]);
    } finally {
      if (timer) clearTimeout(timer);
    }
  }

  getState() {
    return {
      name: this.name,
      active: this._active,
      pending: this._pending,
      idle: !this._active && this._pending === 0,
    };
  }
}

module.exports = { SerialTaskQueue };
