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

// Test: session properties (PATH-03, PATH-06, PATH-07, PATH-08,
// CERT-01, CERT-02, CERT-03, CERT-04, CERT-05).
// PATH-03/06: session.path returns { local, remote } with addresses.
// session.path is cached (same object on second access).
// session.path returns undefined after destroy.
// session.certificate returns own cert object.
// session.peerCertificate returns peer cert.
// session.ephemeralKeyInfo returns key info on client.
// All three cached.
// All three return undefined after destroy.

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

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

const { X509Certificate } = await import('node:crypto');

// The QUIC test helpers configure both sides with the agent1 fixture cert,
const expectedCert = new X509Certificate(fixtures.readKey('agent1-cert.pem'));

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

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

const serverDone = Promise.withResolvers();

const serverEndpoint = await listen(mustCall(async (serverSession) => {
  await serverSession.opened;

  // PATH-03/06: Server path has local and remote.
  const path = serverSession.path;
  assert.ok(path);
  assert.ok(path.local);
  assert.ok(path.remote);

  // Cached.
  assert.strictEqual(serverSession.path, path);

  // Own certificate.
  const cert = serverSession.certificate;
  assert.ok(cert instanceof X509Certificate);
  assert.strictEqual(cert.subject, expectedCert.subject);
  assert.strictEqual(cert.issuer, expectedCert.issuer);
  assert.strictEqual(cert.fingerprint256, expectedCert.fingerprint256);

  // Peer certificate (client's cert — not set in this
  // test since we don't use verifyClient, so it's undefined).
  assert.strictEqual(serverSession.peerCertificate, undefined);

  // Cached.
  assert.strictEqual(serverSession.certificate, cert);

  await serverSession.close();
  serverDone.resolve();
}));

const clientSession = await connect(serverEndpoint.address);
await clientSession.opened;

// PATH-03/06: Client path.
const path = clientSession.path;
assert.ok(path);
assert.ok(path.local);
assert.ok(path.remote);

// Cached.
assert.strictEqual(clientSession.path, path);

// Peer certificate (server's cert).
const peerCert = clientSession.peerCertificate;
assert.ok(peerCert instanceof X509Certificate);
assert.strictEqual(peerCert.subject, expectedCert.subject);
assert.strictEqual(peerCert.issuer, expectedCert.issuer);
assert.strictEqual(peerCert.fingerprint256, expectedCert.fingerprint256);

// Ephemeral key info (client only).
const keyInfo = clientSession.ephemeralKeyInfo;
assert.ok(keyInfo);

// Cached.
assert.strictEqual(clientSession.peerCertificate, peerCert);
assert.strictEqual(clientSession.ephemeralKeyInfo, keyInfo);

await Promise.all([clientSession.closed, serverDone.promise]);

// Returns undefined after destroy.
assert.strictEqual(clientSession.path, undefined);

// Returns undefined after destroy.
assert.strictEqual(clientSession.certificate, undefined);
assert.strictEqual(clientSession.peerCertificate, undefined);
assert.strictEqual(clientSession.ephemeralKeyInfo, undefined);

await serverEndpoint.close();
