import { timingSafeEqual } from "node:crypto";
import { link, mkdir, open, readFile, unlink } from "node:fs/promises";
import { createServer } from "node:http";
import https from "node:https";
import { connect as connectNet } from "node:net";
import { dirname } from "node:path";
import { connect as connectTls } from "node:tls";

const allowedHosts = new Set([
  "api.cesium.com",
  "assets.ion.cesium.com",
  "dev.virtualearth.net",
  "ecn.t0.tiles.virtualearth.net",
  "ecn.t1.tiles.virtualearth.net",
  "ecn.t2.tiles.virtualearth.net",
  "ecn.t3.tiles.virtualearth.net",
]);
const connectionTimingSymbol = Symbol("nodedc.connection-timing");
const config = await readConfig();
const transport = createTransport(config);

const server = createServer(async (request, response) => {
  const url = new URL(request.url || "/", "http://localhost");
  try {
    if (request.method === "GET" && ["/healthz", "/status"].includes(url.pathname)) return writeJson(response, 200, await statusBody());
    if (request.method === "POST" && url.pathname === "/api/pair") return await pairConnector(request, response);
    if (["GET", "HEAD"].includes(request.method || "") && url.pathname === "/proxy/cesium/fetch") return await forwardCesiumRequest(request, response, url);
    return writeJson(response, 404, { ok: false, error: "not_found" });
  } catch (error) {
    if (response.destroyed || response.headersSent || response.writableEnded) {
      if (!response.writableEnded) response.destroy();
      return;
    }
    const errorCode = safeError(error);
    const status = Number(error?.statusCode || 502);
    console.warn(JSON.stringify({ event: "cesium_egress_request_failed", error: errorCode, status, ...telemetryLogFields(error?.telemetry) }));
    return writeJson(response, status, { ok: false, error: errorCode }, { "x-nodedc-egress-error": errorCode });
  }
});

server.listen(config.port, config.bindAddress, () => console.log(JSON.stringify({ event: "dc_amd_proxy_started", bindAddress: config.bindAddress, port: config.port, connector: `${config.connectorHost}:${config.connectorPort}`, directEgress: false })));
for (const signal of ["SIGINT", "SIGTERM"]) process.on(signal, () => server.close(() => transport.close(() => process.exit(0))));

async function readConfig() {
  const nodeEnv = String(process.env.NODE_ENV || "production").trim();
  return {
    port: parsePort(process.env.PORT, 8790),
    bindAddress: parseIpv4(process.env.DC_AMD_PROXY_BIND_ADDRESS || "172.22.0.222", "bind_address"),
    connectorHost: parseIpv4(process.env.DC_AMD_CONNECTOR_HOST || "172.22.0.183", "connector_host"),
    connectorPort: parsePort(process.env.DC_AMD_CONNECTOR_PORT, 8791),
    pairAllowedSource: parseIpv4(process.env.DC_AMD_PAIR_ALLOWED_SOURCE || "172.22.0.183", "pair_allowed_source"),
    connectorTokenFile: String(process.env.DC_AMD_CONNECTOR_TOKEN_FILE || "/var/lib/dc-amd-proxy/connector-access").trim(),
    mapToken: Buffer.from(await readSecretFile(process.env.DC_AMD_MAP_EGRESS_TOKEN_FILE || "/run/nodedc-secrets/map-egress-proxy-token", "map_egress_token"), "utf8"),
    connectTimeoutMs: parseDuration(process.env.DC_AMD_CONNECT_TIMEOUT_SECONDS, 20),
    upstreamTimeoutMs: parseDuration(process.env.DC_AMD_UPSTREAM_TIMEOUT_SECONDS, 30),
    bodyIdleTimeoutMs: parseDuration(process.env.DC_AMD_BODY_IDLE_TIMEOUT_SECONDS, 30),
    poolMaxSockets: parsePoolSize(process.env.DC_AMD_POOL_MAX_SOCKETS, 8),
    poolMaxFreeSockets: parsePoolSize(process.env.DC_AMD_POOL_MAX_FREE_SOCKETS, 4),
    slowRequestMs: parseDuration(process.env.DC_AMD_SLOW_REQUEST_SECONDS, 2),
    allowInsecureTls: nodeEnv === "test" && parseBoolean(process.env.DC_AMD_PROXY_TEST_ALLOW_INSECURE_TLS, false),
  };
}

async function statusBody() {
  const paired = Boolean(await readConnectorToken());
  return {
    ok: true,
    service: "dc-amd-proxy",
    state: paired ? "paired" : "awaiting_pair",
    forwarding: paired ? "amd_connector_only" : "disabled",
    directEgress: false,
    connector: `${config.connectorHost}:${config.connectorPort}`,
    transport: transport.status(),
  };
}

async function pairConnector(request, response) {
  if (normalizeAddress(request.socket.remoteAddress) !== config.pairAllowedSource) return writeJson(response, 403, { ok: false, error: "pair_source_not_allowed" });
  if (await readConnectorToken()) return writeJson(response, 409, { ok: false, error: "already_paired" });
  const body = await readJsonBody(request, 1024);
  const token = String(body?.connectorAccessToken || "").trim();
  if (!isSecret(token)) return writeJson(response, 400, { ok: false, error: "connector_access_token_invalid" });
  await persistConnectorToken(token);
  console.log(JSON.stringify({ event: "amd_connector_paired" }));
  return writeJson(response, 201, { ok: true, state: "paired" });
}

async function forwardCesiumRequest(request, response, requestUrl) {
  if (!isMapAuthorized(request.headers["x-proxy-token"])) return writeJson(response, 401, { ok: false, error: "map_egress_unauthorized" });
  const target = parseTarget(requestUrl.searchParams.get("url") || "");
  const startedAt = Date.now();
  const terminal = transport.beginRequest(target.hostname);
  const controller = new AbortController();
  let telemetry = emptyTelemetry();
  let upstream;
  let responseBytes = 0;
  let upstreamEnded = false;
  let downstreamFinished = false;
  let clientAborted = false;
  let terminalFinished = false;
  let bodyIdleTimer;
  let abortUpstream;
  const clearBodyIdleTimer = () => {
    if (bodyIdleTimer) clearTimeout(bodyIdleTimer);
    bodyIdleTimer = undefined;
  };
  const cleanup = () => {
    clearBodyIdleTimer();
    request.off("aborted", onClientAbort);
    response.off("close", onClientAbort);
    if (abortUpstream) controller.signal.removeEventListener("abort", abortUpstream);
  };
  const finish = (outcome) => {
    if (terminalFinished) return false;
    terminalFinished = terminal.complete({
      ...outcome,
      durationMs: Date.now() - startedAt,
      bytes: responseBytes,
      telemetry,
    });
    if (terminalFinished) cleanup();
    return terminalFinished;
  };
  function onClientAbort() {
    if (downstreamFinished || terminalFinished) return;
    clientAborted = true;
    if (!controller.signal.aborted) controller.abort(abortError());
    // Before headers, requestOnce owns the active/queued ClientRequest and its
    // signal. The await/catch below records its complete attempt telemetry.
    if (upstream) finish({ type: "client-abort" });
  }
  const armBodyIdleTimer = () => {
    clearBodyIdleTimer();
    bodyIdleTimer = setTimeout(() => {
      const error = typedError("amd_upstream_body_idle_timeout", 502);
      error.code = "ETIMEDOUT";
      upstream.destroy(error);
    }, config.bodyIdleTimeoutMs);
    bodyIdleTimer.unref?.();
  };
  request.once("aborted", onClientAbort);
  response.once("close", onClientAbort);

  try {
    const connectorToken = await readConnectorToken();
    if (clientAborted || controller.signal.aborted) {
      finish({ type: "client-abort" });
      return;
    }
    if (!connectorToken) {
      finish({ type: "request-failure", errorCode: "amd_connector_not_paired" });
      return writeJson(response, 503, { ok: false, error: "amd_connector_not_paired" }, { "x-nodedc-egress-error": "amd_connector_not_paired" });
    }
    const result = await requestThroughAmd(target, request.method || "GET", upstreamHeaders(request), controller.signal);
    upstream = result.upstream;
    telemetry = result.telemetry;
    if (clientAborted || controller.signal.aborted) {
      upstream.destroy();
      finish({ type: "client-abort" });
      return;
    }
    abortUpstream = () => {
      if (!upstreamEnded && !upstream.destroyed) upstream.destroy(abortError());
    };
    controller.signal.addEventListener("abort", abortUpstream, { once: true });
    if (controller.signal.aborted) abortUpstream();

    upstream.on("data", (chunk) => {
      responseBytes += chunk.length;
      armBodyIdleTimer();
    });
    upstream.once("end", () => {
      upstreamEnded = true;
      clearBodyIdleTimer();
    });
    upstream.once("error", (error) => {
      upstreamEnded = true;
      clearBodyIdleTimer();
      if (!finish({ type: clientAborted ? "client-abort" : "stream-failure", errorCode: safeTransportError(error) })) return;
      if (!clientAborted) {
        console.warn(JSON.stringify({ event: "cesium_egress_stream_failed", host: target.hostname, error: safeTransportError(error), bytes: responseBytes }));
      }
      if (!response.destroyed) response.destroy();
    });
    armBodyIdleTimer();
    response.writeHead(upstream.statusCode || 502, safeResponseHeaders(upstream.headers));
    response.once("finish", () => {
      downstreamFinished = true;
      clearBodyIdleTimer();
      const durationMs = Date.now() - startedAt;
      const status = Number(upstream.statusCode || 502);
      if (!finish({ type: "response", status })) return;
      // Normal tile traffic is intentionally not logged per object. Slow or
      // failing responses are sufficient to diagnose VPN/transport regressions
      // without creating a noisy, credential-bearing request log.
      if (durationMs >= config.slowRequestMs || status >= 400) {
        console.warn(JSON.stringify({
          event: "cesium_egress_slow_or_failed",
          host: target.hostname,
          status,
          durationMs,
          queueMs: telemetry.queueMs,
          connectionMs: telemetry.connectionMs,
          ttfbMs: telemetry.ttfbMs,
          retryMs: telemetry.retryMs,
          attempts: telemetry.attempts,
          bytes: responseBytes,
          reusedSocket: telemetry.reusedSocket,
          retries: telemetry.retries,
        }));
      }
    });
    upstream.pipe(response);
  } catch (error) {
    telemetry = mergeTelemetry(telemetry, error?.telemetry);
    if (clientAborted || controller.signal.aborted) {
      finish({ type: "client-abort" });
      return;
    }
    if (upstream && !upstream.destroyed) upstream.destroy();
    finish({ type: "request-failure", errorCode: safeTransportError(error) });
    error.telemetry = telemetry;
    throw error;
  }
}

async function requestThroughAmd(initialTarget, method, headers, signal) {
  let target = initialTarget;
  let requestHeaders = { ...headers };
  let aggregate = emptyTelemetry();
  for (let redirects = 0; redirects <= 5; redirects += 1) {
    let result;
    try {
      result = await requestWithSafeRetry(target, method, requestHeaders, signal);
    } catch (error) {
      error.telemetry = mergeTelemetry(aggregate, error?.telemetry);
      throw error;
    }
    const { upstream } = result;
    aggregate = mergeTelemetry(aggregate, result.telemetry);
    const statusCode = Number(upstream.statusCode || 502);
    const location = Array.isArray(upstream.headers.location) ? upstream.headers.location[0] : upstream.headers.location;
    if ([301, 302, 303, 307, 308].includes(statusCode) && location) {
      try {
        aggregate.attemptMs += await drainRedirect(upstream, signal);
        const redirectedTarget = parseTarget(new URL(location, target).toString());
        if (redirectedTarget.origin !== target.origin) requestHeaders = withoutAuthorization(requestHeaders);
        target = redirectedTarget;
      } catch (error) {
        aggregate.attemptMs += Math.max(0, Number(error?.redirectDrainMs || 0));
        error.telemetry = aggregate;
        throw error;
      }
      continue;
    }
    return { upstream, telemetry: aggregate };
  }
  const error = typedError("amd_upstream_redirect_limit", 502);
  error.telemetry = aggregate;
  throw error;
}

function withoutAuthorization(headers) {
  const output = { ...headers };
  delete output.authorization;
  return output;
}

function drainRedirect(upstream, signal) {
  return new Promise((resolve, reject) => {
    const startedAt = Date.now();
    let finished = false;
    let idleTimer;
    const cleanup = () => {
      if (idleTimer) clearTimeout(idleTimer);
      signal.removeEventListener("abort", onAbort);
      upstream.off("data", armIdleTimer);
      upstream.off("end", onEnd);
      upstream.off("aborted", onUpstreamAbort);
      upstream.off("error", onError);
    };
    const complete = () => {
      if (finished) return;
      finished = true;
      cleanup();
      resolve(Date.now() - startedAt);
    };
    const fail = (error) => {
      if (finished) return;
      finished = true;
      cleanup();
      error.redirectDrainMs = Date.now() - startedAt;
      upstream.destroy();
      reject(error);
    };
    const armIdleTimer = () => {
      if (idleTimer) clearTimeout(idleTimer);
      idleTimer = setTimeout(() => {
        const error = typedError("amd_upstream_redirect_body_idle_timeout", 502);
        error.code = "ETIMEDOUT";
        fail(error);
      }, config.bodyIdleTimeoutMs);
      idleTimer.unref?.();
    };
    const onAbort = () => fail(abortReason(signal));
    const onEnd = () => complete();
    const onUpstreamAbort = () => {
      const error = typedError("amd_upstream_redirect_aborted", 502);
      error.code = "ECONNRESET";
      fail(error);
    };
    const onError = (error) => fail(error);
    signal.addEventListener("abort", onAbort, { once: true });
    upstream.on("data", armIdleTimer);
    upstream.once("end", onEnd);
    upstream.once("aborted", onUpstreamAbort);
    upstream.once("error", onError);
    if (signal.aborted) onAbort();
    else {
      armIdleTimer();
      upstream.resume();
    }
  });
}

async function requestWithSafeRetry(target, method, headers, signal) {
  let retries = 0;
  let aggregate = emptyTelemetry();
  while (true) {
    try {
      const result = await requestOnce(target, method, headers, signal);
      aggregate = mergeTelemetry(aggregate, result.telemetry);
      aggregate.retries = retries;
      if (retries > 0) {
        console.warn(JSON.stringify({
          event: "cesium_egress_retry_completed",
          host: target.hostname,
          attempt: retries + 1,
          status: Number(result.upstream.statusCode || 502),
          ...telemetryLogFields(result.telemetry),
          totalAttemptMs: aggregate.attemptMs,
        }));
      }
      return { upstream: result.upstream, telemetry: aggregate };
    } catch (error) {
      const failedAttemptTelemetry = error?.telemetry;
      aggregate = mergeTelemetry(aggregate, failedAttemptTelemetry);
      if (signal.aborted || retries >= 1 || !["GET", "HEAD"].includes(method) || error?.reusedSocket !== true || !isRetryableSocketError(error)) {
        if (retries > 0) {
          console.warn(JSON.stringify({
            event: "cesium_egress_retry_failed",
            host: target.hostname,
            attempt: retries + 1,
            error: safeTransportError(error),
            ...telemetryLogFields(failedAttemptTelemetry),
            totalAttemptMs: aggregate.attemptMs,
          }));
        }
        error.telemetry = aggregate;
        throw error;
      }
      retries += 1;
      aggregate.retryMs += Number(error?.telemetry?.attemptMs || 0);
      aggregate.retries = retries;
      const errorCode = safeTransportError(error);
      transport.recordRetry(target.hostname, errorCode);
      console.warn(JSON.stringify({
        event: "cesium_egress_reused_socket_retry",
        host: target.hostname,
        attempt: retries,
        error: errorCode,
        ...telemetryLogFields(failedAttemptTelemetry),
      }));
    }
  }
}

function requestOnce(target, method, headers, externalSignal) {
  return new Promise((resolve, reject) => {
    const startedAt = Date.now();
    let socketAssignedAt = null;
    let socketTiming = null;
    let reusedSocket = false;
    let settled = false;
    let timedOut = false;
    const pendingConnectionTiming = { startedAt: null, readyAt: null };
    const attemptController = new AbortController();
    const abortAttempt = () => {
      if (!attemptController.signal.aborted) attemptController.abort(abortReason(externalSignal));
    };
    if (externalSignal.aborted) abortAttempt();
    else externalSignal.addEventListener("abort", abortAttempt, { once: true });
    const client = https.request({
      protocol: "https:",
      hostname: target.hostname,
      port: 443,
      method,
      path: `${target.pathname || "/"}${target.search || ""}`,
      headers,
      agent: transport.agent,
      signal: attemptController.signal,
      nodedcAbortSignal: attemptController.signal,
      nodedcConnectionTiming: pendingConnectionTiming,
    });
    transport.observeQueuePeak();
    queueMicrotask(() => transport.observeQueuePeak());
    const timeoutError = typedError("amd_upstream_timeout", 502);
    timeoutError.code = "ETIMEDOUT";
    const timeout = setTimeout(() => {
      timedOut = true;
      if (!attemptController.signal.aborted) attemptController.abort(timeoutError);
    }, config.upstreamTimeoutMs);
    timeout.unref?.();
    const cleanup = () => {
      clearTimeout(timeout);
      externalSignal.removeEventListener("abort", abortAttempt);
    };
    const attemptTelemetry = (endedAt, receivedHeaders, error) => {
      const failedConnectionTiming = error?.[connectionTimingSymbol];
      const timing = socketTiming || failedConnectionTiming || (pendingConnectionTiming.startedAt ? pendingConnectionTiming : null);
      const newConnection = !reusedSocket && timing;
      const queueEnd = newConnection?.startedAt || socketAssignedAt || endedAt;
      const connectionMs = newConnection ? Math.max(0, Number(newConnection.readyAt || endedAt) - Number(newConnection.startedAt || endedAt)) : 0;
      return {
        queueMs: Math.max(0, Number(queueEnd) - startedAt),
        connectionMs,
        ttfbMs: receivedHeaders && socketAssignedAt ? Math.max(0, endedAt - socketAssignedAt) : 0,
        attemptMs: Math.max(0, endedAt - startedAt),
        retryMs: 0,
        attempts: 1,
        retries: 0,
        reusedSocket,
      };
    };
    client.once("socket", (socket) => {
      socketAssignedAt = Date.now();
      socketTiming = socket[connectionTimingSymbol] || null;
      const priorAssignments = Number(socketTiming?.assignments || 0);
      reusedSocket = client.reusedSocket === true || priorAssignments > 0;
      if (socketTiming) socketTiming.assignments = priorAssignments + 1;
    });
    client.once("error", (rawError) => {
      if (settled) return;
      settled = true;
      cleanup();
      const error = timedOut && !externalSignal.aborted ? timeoutError : externalSignal.aborted ? abortReason(externalSignal) : rawError;
      if (rawError?.[connectionTimingSymbol] && !error[connectionTimingSymbol]) error[connectionTimingSymbol] = rawError[connectionTimingSymbol];
      error.reusedSocket = reusedSocket || client.reusedSocket === true;
      error.telemetry = attemptTelemetry(Date.now(), false, error);
      reject(error);
    });
    client.once("response", (upstream) => {
      if (settled) {
        upstream.destroy();
        return;
      }
      settled = true;
      cleanup();
      const endedAt = Date.now();
      resolve({
        upstream,
        telemetry: attemptTelemetry(endedAt, true),
      });
    });
    client.end();
    transport.observeQueuePeak();
  });
}

function emptyTelemetry() {
  return { queueMs: 0, connectionMs: 0, ttfbMs: 0, attemptMs: 0, retryMs: 0, attempts: 0, retries: 0, reusedSocket: false };
}

function telemetryLogFields(telemetry) {
  if (!telemetry) return {};
  return {
    queueMs: Math.max(0, Number(telemetry.queueMs || 0)),
    connectionMs: Math.max(0, Number(telemetry.connectionMs || 0)),
    ttfbMs: Math.max(0, Number(telemetry.ttfbMs || 0)),
    attemptMs: Math.max(0, Number(telemetry.attemptMs || 0)),
    retryMs: Math.max(0, Number(telemetry.retryMs || 0)),
    attempts: Math.max(0, Number(telemetry.attempts || 0)),
    retries: Math.max(0, Number(telemetry.retries || 0)),
    reusedSocket: telemetry.reusedSocket === true,
  };
}

function mergeTelemetry(left, right) {
  const merged = { ...emptyTelemetry(), ...(left || {}) };
  if (!right) return merged;
  for (const name of ["queueMs", "connectionMs", "ttfbMs", "attemptMs", "retryMs", "attempts", "retries"]) {
    if (name === "retries") merged[name] = Math.max(Number(merged[name] || 0), Number(right[name] || 0));
    else merged[name] += Math.max(0, Number(right[name] || 0));
  }
  merged.reusedSocket ||= right.reusedSocket === true;
  return merged;
}

function createTransport(runtimeConfig) {
  const metrics = {
    openedTunnels: 0,
    tunnelFailures: 0,
    requests: 0,
    terminalRequests: 0,
    inFlightRequests: 0,
    completedResponses: 0,
    failedRequests: 0,
    slowRequests: 0,
    responseBytes: 0,
    partialBytes: 0,
    reusedSocketRequests: 0,
    retries: 0,
    streamFailures: 0,
    clientAborts: 0,
    maxQueuedRequests: 0,
    timing: {
      queueMs: { total: 0, max: 0 },
      connectionMs: { total: 0, max: 0 },
      ttfbMs: { total: 0, max: 0 },
      attemptMs: { total: 0, max: 0 },
      retryMs: { total: 0, max: 0 },
      durationMs: { total: 0, max: 0 },
    },
    byHost: {},
    lastFailure: null,
    lastFailureAt: null,
  };
  const agent = new https.Agent({
    keepAlive: true,
    keepAliveMsecs: 30_000,
    maxSockets: runtimeConfig.poolMaxSockets,
    maxFreeSockets: runtimeConfig.poolMaxFreeSockets,
    scheduling: "lifo",
  });
  // https.Agent maintains a separate pool per origin. A Cesium/Bing tile
  // therefore reuses an already authenticated NAS -> AMD -> VPN -> TLS path
  // for its host instead of paying a fresh CONNECT and TLS handshake.
  agent.createConnection = (options, callback) => {
    const hostname = String(options.servername || options.hostname || options.host || "").toLowerCase();
    const signal = options.nodedcAbortSignal;
    const pendingConnectionTiming = options.nodedcConnectionTiming;
    void (async () => {
      if (!allowedHosts.has(hostname)) throw typedError("cesium_target_not_allowed", 403);
      const connectorToken = await readConnectorToken();
      if (!connectorToken) throw typedError("amd_connector_not_paired", 503);
      const startedAt = Date.now();
      if (pendingConnectionTiming) pendingConnectionTiming.startedAt = startedAt;
      let connectedAt = startedAt;
      try {
        const tunnel = await openConnectorTunnel({ hostname }, connectorToken, signal);
        connectedAt = Date.now();
        const secureSocket = await openTlsTunnel(tunnel, hostname, signal);
        const readyAt = Date.now();
        if (pendingConnectionTiming) pendingConnectionTiming.readyAt = readyAt;
        secureSocket[connectionTimingSymbol] = { startedAt, readyAt, assignments: 0 };
        metrics.openedTunnels += 1;
        console.log(JSON.stringify({
          event: "cesium_egress_tunnel_opened",
          host: hostname,
          connectorMs: connectedAt - startedAt,
          tlsMs: readyAt - connectedAt,
        }));
        callback(null, secureSocket);
      } catch (error) {
        const readyAt = Date.now();
        if (pendingConnectionTiming) pendingConnectionTiming.readyAt = readyAt;
        error[connectionTimingSymbol] = { startedAt, readyAt, assignments: 0 };
        throw error;
      }
    })().catch((error) => {
      const errorCode = safeError(error);
      if (error?.code !== "ABORT_ERR") {
        metrics.tunnelFailures += 1;
        metrics.lastFailure = errorCode;
        metrics.lastFailureAt = new Date().toISOString();
      }
      callback(error);
    });
    return undefined;
  };

  return {
    agent,
    close(callback) { agent.destroy(); callback(); },
    beginRequest(host) {
      const hostMetrics = perHostMetrics(metrics, host);
      metrics.requests += 1;
      hostMetrics.requests += 1;
      metrics.inFlightRequests += 1;
      hostMetrics.inFlightRequests += 1;
      let finished = false;
      return {
        complete({ type, status = 0, durationMs = 0, bytes = 0, telemetry = emptyTelemetry(), errorCode = "" }) {
          if (finished) return false;
          finished = true;
          metrics.terminalRequests += 1;
          metrics.inFlightRequests = Math.max(0, metrics.inFlightRequests - 1);
          hostMetrics.terminalRequests += 1;
          hostMetrics.inFlightRequests = Math.max(0, hostMetrics.inFlightRequests - 1);
          const safeBytes = Math.max(0, Number(bytes || 0));
          if (telemetry.reusedSocket) {
            metrics.reusedSocketRequests += 1;
            hostMetrics.reusedSocketRequests += 1;
          }
          observe(metrics.timing.queueMs, telemetry.queueMs);
          observe(metrics.timing.connectionMs, telemetry.connectionMs);
          observe(metrics.timing.ttfbMs, telemetry.ttfbMs);
          observe(metrics.timing.attemptMs, telemetry.attemptMs);
          observe(metrics.timing.retryMs, telemetry.retryMs);
          observe(metrics.timing.durationMs, durationMs);
          if (type === "response") {
            metrics.completedResponses += 1;
            hostMetrics.completedResponses += 1;
            metrics.responseBytes += safeBytes;
            hostMetrics.bytes += safeBytes;
          } else {
            metrics.partialBytes += safeBytes;
            hostMetrics.partialBytes += safeBytes;
          }
          if (type === "client-abort") {
            metrics.clientAborts += 1;
            hostMetrics.clientAborts += 1;
          }
          const failure = type === "stream-failure" || type === "request-failure" || type === "response" && Number(status) >= 400;
          if (failure) {
            metrics.failedRequests += 1;
            hostMetrics.failedRequests += 1;
            if (type === "stream-failure") {
              metrics.streamFailures += 1;
              hostMetrics.streamFailures += 1;
            }
            metrics.lastFailure = errorCode || `upstream_http_${status}`;
            metrics.lastFailureAt = new Date().toISOString();
            hostMetrics.lastTransportError = errorCode || `upstream_http_${status}`;
          }
          if (type !== "client-abort" && durationMs >= runtimeConfig.slowRequestMs) metrics.slowRequests += 1;
          return true;
        },
      };
    },
    recordRetry(host, errorCode) {
      metrics.retries += 1;
      const hostMetrics = perHostMetrics(metrics, host);
      hostMetrics.retries += 1;
      hostMetrics.lastTransportError = errorCode;
    },
    observeQueuePeak() {
      const queuedRequests = socketCount(agent.requests);
      metrics.maxQueuedRequests = Math.max(metrics.maxQueuedRequests, queuedRequests);
    },
    status() {
      const queuedRequests = socketCount(agent.requests);
      metrics.maxQueuedRequests = Math.max(metrics.maxQueuedRequests, queuedRequests);
      return {
        pool: {
          activeSockets: socketCount(agent.sockets),
          idleSockets: socketCount(agent.freeSockets),
          queuedRequests,
          maxQueuedRequests: metrics.maxQueuedRequests,
          maxSockets: runtimeConfig.poolMaxSockets,
          maxFreeSockets: runtimeConfig.poolMaxFreeSockets,
          byOrigin: poolByOrigin(agent),
        },
        metrics: publicTransportMetrics(metrics),
      };
    },
  };
}

function perHostMetrics(metrics, host) {
  const safeHost = allowedHosts.has(String(host || "").toLowerCase()) ? String(host).toLowerCase() : "unknown";
  metrics.byHost[safeHost] ||= {
    requests: 0,
    terminalRequests: 0,
    inFlightRequests: 0,
    completedResponses: 0,
    failedRequests: 0,
    reusedSocketRequests: 0,
    retries: 0,
    streamFailures: 0,
    clientAborts: 0,
    bytes: 0,
    partialBytes: 0,
    lastTransportError: null,
  };
  return metrics.byHost[safeHost];
}

function observe(bucket, rawValue) {
  const value = Math.max(0, Number(rawValue || 0));
  bucket.total += value;
  bucket.max = Math.max(bucket.max, value);
}

function publicTransportMetrics(metrics) {
  const average = (bucket) => metrics.terminalRequests ? Math.round(bucket.total / metrics.terminalRequests) : 0;
  return {
    openedTunnels: metrics.openedTunnels,
    tunnelFailures: metrics.tunnelFailures,
    requests: metrics.requests,
    terminalRequests: metrics.terminalRequests,
    inFlightRequests: metrics.inFlightRequests,
    completedResponses: metrics.completedResponses,
    failedRequests: metrics.failedRequests,
    slowRequests: metrics.slowRequests,
    responseBytes: metrics.responseBytes,
    partialBytes: metrics.partialBytes,
    reusedSocketRequests: metrics.reusedSocketRequests,
    retries: metrics.retries,
    streamFailures: metrics.streamFailures,
    clientAborts: metrics.clientAborts,
    timing: {
      queueMs: { average: average(metrics.timing.queueMs), max: metrics.timing.queueMs.max },
      connectionMs: { average: average(metrics.timing.connectionMs), max: metrics.timing.connectionMs.max },
      ttfbMs: { average: average(metrics.timing.ttfbMs), max: metrics.timing.ttfbMs.max },
      attemptMs: { average: average(metrics.timing.attemptMs), max: metrics.timing.attemptMs.max },
      retryMs: { average: average(metrics.timing.retryMs), max: metrics.timing.retryMs.max },
      durationMs: { average: average(metrics.timing.durationMs), max: metrics.timing.durationMs.max },
    },
    byHost: metrics.byHost,
    lastFailure: metrics.lastFailure,
    lastFailureAt: metrics.lastFailureAt,
  };
}

function poolByOrigin(agent) {
  const origins = {};
  for (const [key, sockets] of Object.entries(agent.sockets)) poolOrigin(origins, key).active += sockets.length;
  for (const [key, sockets] of Object.entries(agent.freeSockets)) poolOrigin(origins, key).idle += sockets.length;
  for (const [key, requests] of Object.entries(agent.requests)) poolOrigin(origins, key).queued += requests.length;
  return origins;
}

function poolOrigin(origins, agentKey) {
  const host = String(agentKey || "").split(":")[0].toLowerCase();
  const safeHost = allowedHosts.has(host) ? host : "unknown";
  origins[safeHost] ||= { active: 0, idle: 0, queued: 0 };
  return origins[safeHost];
}

function openConnectorTunnel(target, connectorToken, signal) {
  return new Promise((resolve, reject) => {
    if (signal?.aborted) {
      reject(abortReason(signal));
      return;
    }
    const socket = connectNet({ host: config.connectorHost, port: config.connectorPort });
    let buffer = Buffer.alloc(0);
    let finished = false;
    const timeoutError = typedError("amd_connector_timeout", 502);
    timeoutError.code = "ETIMEDOUT";
    const timeout = setTimeout(() => fail(timeoutError), config.connectTimeoutMs);
    timeout.unref?.();
    const cleanup = () => {
      clearTimeout(timeout);
      signal?.removeEventListener("abort", onAbort);
      socket.off("connect", onConnect);
      socket.off("error", fail);
      socket.off("data", onData);
    };
    const finish = (value) => {
      if (finished) return;
      finished = true;
      cleanup();
      resolve(value);
    };
    const fail = (error) => {
      if (finished) return;
      finished = true;
      cleanup();
      socket.destroy();
      reject(error);
    };
    const onAbort = () => fail(abortReason(signal));
    const onConnect = () => socket.write(`CONNECT ${target.hostname}:443 HTTP/1.1\r\nHost: ${target.hostname}:443\r\nProxy-Authorization: Bearer ${connectorToken}\r\n\r\n`);
    const onData = (chunk) => {
      buffer = Buffer.concat([buffer, chunk]);
      if (buffer.length > 16 * 1024) return fail(typedError("amd_connector_response_invalid", 502));
      const end = buffer.indexOf("\r\n\r\n");
      if (end < 0) return;
      if (!/^HTTP\/1\.[01] 200\b/.test(buffer.subarray(0, end).toString("ascii"))) return fail(typedError("amd_connector_rejected", 502));
      const remainder = buffer.subarray(end + 4);
      if (remainder.length) socket.unshift(remainder);
      finish(socket);
    };
    signal?.addEventListener("abort", onAbort, { once: true });
    socket.once("connect", onConnect);
    socket.on("error", fail);
    socket.on("data", onData);
  });
}

function openTlsTunnel(socket, hostname, signal) {
  return new Promise((resolve, reject) => {
    if (signal?.aborted) {
      socket.destroy();
      reject(abortReason(signal));
      return;
    }
    const secureSocket = connectTls({ socket, servername: hostname, ALPNProtocols: ["http/1.1"], rejectUnauthorized: !config.allowInsecureTls });
    let finished = false;
    const timeoutError = typedError("amd_upstream_tls_timeout", 502);
    timeoutError.code = "ETIMEDOUT";
    const timeout = setTimeout(() => fail(timeoutError), config.connectTimeoutMs);
    timeout.unref?.();
    const cleanup = () => {
      clearTimeout(timeout);
      signal?.removeEventListener("abort", onAbort);
      secureSocket.off("secureConnect", finish);
      secureSocket.off("error", fail);
    };
    const finish = () => {
      if (finished) return;
      finished = true;
      cleanup();
      resolve(secureSocket);
    };
    const fail = (error) => {
      if (finished) return;
      finished = true;
      cleanup();
      secureSocket.destroy();
      reject(error);
    };
    const onAbort = () => fail(abortReason(signal));
    signal?.addEventListener("abort", onAbort, { once: true });
    secureSocket.once("secureConnect", finish);
    secureSocket.once("error", fail);
  });
}

function upstreamHeaders(request) {
  // Do not force `Connection: close`: the shared Agent owns a deliberately
  // bounded keep-alive pool for the approved upstream hosts.
  const headers = { accept: safeHeader(request.headers.accept, "*/*"), "accept-encoding": "identity" };
  for (const name of ["range", "if-none-match", "if-modified-since"]) {
    const value = safeHeader(request.headers[name], "");
    if (value) headers[name] = value;
  }
  const authorization = safeHeader(request.headers["x-nodedc-cesium-authorization"], "");
  if (authorization) headers.authorization = authorization;
  const referer = safeHeader(request.headers["x-nodedc-map-referer"], "");
  if (referer) headers.referer = referer;
  return headers;
}

function safeResponseHeaders(headers) {
  const output = {};
  const skipped = new Set(["connection", "keep-alive", "proxy-authenticate", "proxy-authorization", "te", "trailer", "transfer-encoding", "upgrade"]);
  for (const [name, raw] of Object.entries(headers)) {
    if (skipped.has(name.toLowerCase()) || raw === undefined) continue;
    const value = Array.isArray(raw) ? raw.join(", ") : String(raw);
    if (value.length <= 8192 && !/[\r\n\u0000]/.test(value)) output[name] = value;
  }
  return output;
}

function parseTarget(value) {
  let target;
  try { target = new URL(String(value)); } catch { throw typedError("cesium_target_invalid", 400); }
  if (target.protocol !== "https:" || target.username || target.password || target.port && target.port !== "443" || !allowedHosts.has(target.hostname.toLowerCase())) throw typedError("cesium_target_not_allowed", 403);
  target.hostname = target.hostname.toLowerCase();
  return target;
}

async function readConnectorToken() {
  try {
    const token = (await readFile(config.connectorTokenFile, "utf8")).trim();
    return isSecret(token) ? token : null;
  } catch (error) {
    if (error?.code === "ENOENT") return null;
    throw typedError("connector_pair_state_unreadable", 500);
  }
}

async function persistConnectorToken(token) {
  await mkdir(dirname(config.connectorTokenFile), { recursive: true, mode: 0o700 });
  const temporary = `${config.connectorTokenFile}.${process.pid}.${Date.now()}.tmp`;
  let handle;
  try {
    handle = await open(temporary, "wx", 0o600);
    await handle.writeFile(`${token}\n`, "ascii");
    await handle.sync();
    await handle.close();
    handle = null;
    // link(2) is the compare-and-set: unlike rename(), it cannot overwrite an
    // existing pair state. Two concurrent pair attempts therefore produce one
    // durable secret and one harmless 409 response.
    try {
      await link(temporary, config.connectorTokenFile);
    } catch (error) {
      if (error?.code === "EEXIST") throw typedError("already_paired", 409);
      throw error;
    }
  } finally {
    if (handle) await handle.close();
    await unlink(temporary).catch(() => {});
  }
}

async function readSecretFile(path, label) {
  let value;
  try { value = (await readFile(String(path), "utf8")).trim(); } catch { throw new Error(`${label}_unreadable`); }
  if (!value || value.length > 4096 || /[\u0000-\u001f\u007f\s]/.test(value)) throw new Error(`${label}_invalid`);
  return value;
}

function isMapAuthorized(raw) {
  if (Array.isArray(raw)) return false;
  const candidate = Buffer.from(String(raw || ""), "utf8");
  return candidate.length === config.mapToken.length && timingSafeEqual(candidate, config.mapToken);
}

function readJsonBody(request, maxBytes) {
  return new Promise((resolve, reject) => {
    const chunks = [];
    let bytes = 0;
    request.on("data", (chunk) => {
      bytes += chunk.length;
      if (bytes > maxBytes) return reject(typedError("pair_payload_too_large", 413));
      chunks.push(chunk);
    });
    request.once("error", reject);
    request.once("end", () => {
      try { resolve(JSON.parse(Buffer.concat(chunks).toString("utf8"))); } catch { reject(typedError("pair_payload_invalid", 400)); }
    });
  });
}

function writeJson(response, status, body, extraHeaders = {}) {
  const payload = JSON.stringify(body);
  response.writeHead(status, {
    "content-type": "application/json; charset=utf-8",
    "content-length": Buffer.byteLength(payload),
    "cache-control": "no-store",
    ...extraHeaders,
  });
  response.end(payload);
}

function parsePort(raw, fallback) {
  const value = Number(String(raw || fallback).trim());
  if (!Number.isInteger(value) || value < 1024 || value > 65535) throw new Error("invalid_port");
  return value;
}

function parseDuration(raw, fallbackSeconds) {
  const value = Number(String(raw || fallbackSeconds).trim());
  if (!Number.isInteger(value) || value < 1 || value > 120) throw new Error("invalid_duration");
  return value * 1000;
}

function parsePoolSize(raw, fallback) {
  const value = Number(String(raw || fallback).trim());
  if (!Number.isInteger(value) || value < 1 || value > 32) throw new Error("invalid_pool_size");
  return value;
}

function socketCount(table) {
  return Object.values(table).reduce((total, sockets) => total + (Array.isArray(sockets) ? sockets.length : 0), 0);
}

function parseIpv4(raw, label) {
  const value = String(raw || "").trim();
  const octets = value.split(".").map(Number);
  if (octets.length !== 4 || octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)) throw new Error(`${label}_invalid`);
  return value;
}

function normalizeAddress(value) { return String(value || "").replace(/^::ffff:/, ""); }
function safeHeader(raw, fallback) {
  if (Array.isArray(raw)) return fallback;
  const value = String(raw || "").trim();
  return value.length <= 4096 && !/[\r\n\u0000]/.test(value) ? value : fallback;
}
function parseBoolean(value, fallback) { return value === undefined || value === "" ? fallback : ["1", "true", "yes", "on"].includes(String(value).trim().toLowerCase()); }
function isSecret(value) { return /^[A-Za-z0-9_-]{48,256}$/.test(value); }
function typedError(message, statusCode) { const error = new Error(message); error.statusCode = statusCode; return error; }
function abortError() { const error = typedError("amd_client_aborted", 499); error.code = "ABORT_ERR"; return error; }
function abortReason(signal) { return signal?.reason instanceof Error ? signal.reason : abortError(); }
function safeError(error) { return String(error?.message || "dc_amd_proxy_error").replace(/[^A-Za-z0-9_.:-]/g, "_").slice(0, 120); }
function isRetryableSocketError(error) { return new Set(["ECONNRESET", "EPIPE", "ETIMEDOUT", "ECONNABORTED"]).has(String(error?.code || "").toUpperCase()); }
function safeTransportError(error) {
  const code = String(error?.code || "").trim().toLowerCase();
  if (/^[a-z0-9_]{1,48}$/.test(code)) return `amd_upstream_${code}`;
  return safeError(error);
}
