// Flags: --experimental-quic --no-warnings

// Test: onerror callback behavior
// session.onerror fires when session is destroyed with error.
// session.onerror receives the original error as argument.
// session.closed rejects with the original error after onerror.
// session.onerror not called when destroy() has no error.

import { hasQuic, skip, mustCall, mustNotCall } from '../common/index.mjs';
import assert from 'node:assert';
import dc from 'node:diagnostics_channel';

const { ok, rejects, strictEqual } = assert;

if (!hasQuic) {
  skip('QUIC is not enabled');
}

const { listen, connect } = await import('../common/quic.mjs');

// quic.session.error fires when a session is destroyed with an error.
// It should fire once for the first client session (destroyed with error)
// and not for the second (destroyed without error).
dc.subscribe('quic.session.error', mustCall((msg) => {
  ok(msg.session, 'session.error should include session');
  ok(msg.error, 'session.error should include error');
}));

const transportParams = { maxIdleTimeout: 1 };

// All tested using a single endpoint with two client sessions.
const serverEndpoint = await listen(mustCall(async (serverSession) => {
  await serverSession.closed;
}, 2), { transportParams });

// First client: destroy WITH error — onerror fires.
{
  const testError = new Error('destroy with error');
  const clientSession = await connect(serverEndpoint.address, {
    transportParams,
  });
  await clientSession.opened;

  let onerrorCalled = false;
  clientSession.onerror = mustCall((err) => {
    // Receives the original error.
    strictEqual(err, testError);
    onerrorCalled = true;
  });

  clientSession.destroy(testError);

  // Onerror was called synchronously during destroy.
  strictEqual(onerrorCalled, true);

  // Closed rejects with the original error.
  await rejects(clientSession.closed, testError);
}

// Second client: destroy WITHOUT error — onerror should NOT fire.
{
  const clientSession = await connect(serverEndpoint.address, {
    transportParams,
  });
  await clientSession.opened;

  clientSession.onerror = mustNotCall('onerror should not be called');

  clientSession.destroy();

  // Closed resolves (no error).
  await clientSession.closed;
}

await serverEndpoint.close();
