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

import { hasQuic, hasIPv6, skip, mustCall } from '../common/index.mjs';
import assert from 'node:assert';
import * as fixtures from '../common/fixtures.mjs';

const { partialDeepStrictEqual, strictEqual, ok } = assert;
const { readKey } = fixtures;

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

if (!hasIPv6) {
  skip('IPv6 is not supported');
}

// Import after the hasQuic check
const { listen, connect } = await import('node:quic');
const { createPrivateKey } = await import('node:crypto');

const key = createPrivateKey(readKey('agent1-key.pem'));
const cert = readKey('agent1-cert.pem');

const check = {
  // The SNI value
  servername: 'localhost',
  // The selected ALPN protocol
  protocol: 'quic-test',
  // The negotiated cipher suite
  cipher: 'TLS_AES_128_GCM_SHA256',
  cipherVersion: 'TLSv1.3',
};

// The opened promise should resolve when the handshake is complete.

const serverOpened = Promise.withResolvers();

const serverEndpoint = await listen(mustCall(async (serverSession) => {
  const info = await serverSession.opened;
  partialDeepStrictEqual(info, check);
  serverOpened.resolve();
  await serverSession.close();
}), {
  sni: { '*': { keys: [key], certs: [cert] } },
  alpn: ['quic-test'],
  endpoint: {
    address: {
      address: '::1',
      family: 'ipv6',
    },
    ipv6Only: true,
  },
});
// Buffer is not detached.
strictEqual(cert.buffer.detached, false);

// The server must have an address to connect to after listen resolves.
ok(serverEndpoint.address !== undefined);

const clientSession = await connect(serverEndpoint.address, {
  alpn: 'quic-test',
  verifyPeer: 'manual',
  endpoint: {
    address: {
      address: '::',
      family: 'ipv6',
    },
  },
});

const info = await clientSession.opened;
partialDeepStrictEqual(info, check);

await serverOpened.promise;
await clientSession.close();
await serverEndpoint.close();
