// This tests that when using a proxy with an agent with maxSockets: 1,
// subsequent requests are queued when the first request is still alive,
// and processed after the first request completes, and both are sending
// the request through the proxy.

import * as common from '../common/index.mjs';
import assert from 'node:assert';
import { once } from 'events';
import fixtures from '../common/fixtures.js';
import { createProxyServer } from '../common/proxy-server.js';

if (!common.hasCrypto)
  common.skip('missing crypto');

// https must be dynamically imported so that builds without crypto support
// can skip it.
const { default: https } = await import('node:https');

let resolve;
const p = new Promise((r) => { resolve = r; });

// Start a server that delays responses to test queuing behavior
const server = https.createServer({
  cert: fixtures.readKey('agent8-cert.pem'),
  key: fixtures.readKey('agent8-key.pem'),
}, common.mustCall((req, res) => {
  console.log('headers received for', req.url, req.headers);
  if (req.url === '/first') {
    // Simulate a long response for the first request
    p.then(() => {
      console.log('Responding to /first');
      res.writeHead(200, { 'Content-Type': 'text/plain' });
      res.end('Response for /first');
    }).then(common.mustCall());
  } else if (req.url === '/second') {
    // Respond immediately for the second request
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('Response for /second');
  } else {
    assert.fail(`Unexpected request to ${req.url}`);
  }
}, 2));
server.on('error', common.mustNotCall((err) => { console.error('Server error', err); }));
server.listen(0);
await once(server, 'listening');

// Start a minimal proxy server
const { proxy, logs } = createProxyServer();
proxy.listen(0);
await once(proxy, 'listening');

const serverHost = `localhost:${server.address().port}`;
const proxyUrl = `http://localhost:${proxy.address().port}`;

// Create an agent with maxSockets: 1 and proxy support
const agent = new https.Agent({
  maxSockets: 1,
  proxyEnv: {
    HTTPS_PROXY: proxyUrl,
  },
  ca: fixtures.readKey('fake-startcom-root-cert.pem'),
});

const requestTimes = [];

// Make first request that takes longer
const firstReq = https.request({
  hostname: 'localhost',
  port: server.address().port,
  path: '/first',
  agent: agent,
}, common.mustCall((res) => {
  console.log('req1 response received');
  let data = '';
  res.on('data', (chunk) => {
    data += chunk;
  });
  res.on('end', common.mustCall(() => {
    console.log('req1 end');
    requestTimes[0] = { path: '/first', data, endTime: Date.now() };
    assert.strictEqual(data, 'Response for /first');
  }));
}));

firstReq.on('socket', common.mustCall((socket) => {
  console.log('req1 socket acquired');
  // Start second request when first request gets its socket
  // so that it will be queued.
  const secondReq = https.request({
    hostname: 'localhost',
    port: server.address().port,
    path: '/second',
    agent: agent,
  }, common.mustCall((res) => {
    let data = '';
    res.on('data', (chunk) => {
      data += chunk;
    });
    res.on('end', common.mustCall(() => {
      requestTimes[1] = { path: '/second', data, endTime: Date.now() };
      assert.strictEqual(data, 'Response for /second');

      // The two shares the same proxy connection.
      assert.deepStrictEqual(logs, [{
        method: 'CONNECT',
        url: serverHost,
        headers: { 'proxy-connection': 'keep-alive', 'host': serverHost },
      }]);
      proxy.close();
      server.close();
    }));
  }));

  secondReq.on('error', common.mustNotCall());
  firstReq.end();
  secondReq.end();
  resolve();  // Tell the server to respond to the first request
}));

firstReq.on('error', common.mustNotCall());
