import assert from 'node:assert';
import { test } from 'node:test';
import { resolve } from 'node:path';
import Piscina from '../dist';

test('workers are marked as destroyed if destroyed', async () => {
  let index = 0;
  // Its expected to have one task get balanced twice due to the load balancer distribution
  // first task enters, its distributed; second is enqueued, once first is done, second is distributed and normalizes
  let workersFirstRound = [];
  let workersSecondRound = [];
  const pool = new Piscina({
    filename: resolve(__dirname, 'fixtures/eval.js'),
    minThreads: 2,
    maxThreads: 2,
    concurrentTasksPerWorker: 1,
    loadBalancer (_task, workers) {
      if (workersFirstRound.length === 0) {
        workersFirstRound = workers;
        workersSecondRound = workers;
      } else if (
        workersFirstRound[0].id !== workers[0].id
      ) {
        workersSecondRound = workers;
      }
      // Verify distribution to properly test this feature
      const candidate = workers[index++ % workers.length];

      if (candidate.currentUsage !== 0 && !candidate.isRunningAbortableTask) {
        return null;
      }

      return candidate;
    }
  });

  const tasks = [];
  const controller = new AbortController();
  const signal = controller.signal;
  tasks.push(pool.run('while (true) {}', {
    signal
  }));

  for (let n = 0; n < 5; n++) {
    tasks.push(pool.run('new Promise(resolve => setTimeout(resolve, 5))'));
  }

  controller.abort();
  await Promise.allSettled(tasks);
  assert.notStrictEqual(workersFirstRound, workersSecondRound);
  assert.strictEqual(workersFirstRound.length, 2);
  assert.ok(workersFirstRound[0].destroyed);
  assert.ok(!workersFirstRound[0].terminating);
});
