import crypto from "node:crypto";
import { createServer } from "node:http";
import express from "express";
import { WebSocket, WebSocketServer } from "ws";

const DEFAULT_WS_PATH = "/api/ai-workspace/hub";
const MAX_EVENTS_PER_AGENT = 5000;
const MAX_REQUEST_META_PER_AGENT = 1000;
const HEARTBEAT_INTERVAL_MS = 30000;
const AGENT_STALE_MS = 75000;
const DEFAULT_AGENT_EVENT_TEXT_MAX = Number(process.env.AI_WORKSPACE_AGENT_EVENT_TEXT_MAX || 12000);
const CODEX_MESSAGE_EVENT_TEXT_MAX = Number(process.env.AI_WORKSPACE_CODEX_MESSAGE_EVENT_TEXT_MAX || 250000);
const ASSISTANT_RELAY_POLL_TIMEOUT_MS = Number(process.env.AI_WORKSPACE_ASSISTANT_RELAY_POLL_TIMEOUT_MS || 25000);
const ASSISTANT_RELAY_ACTION_TIMEOUT_MS = Number(process.env.AI_WORKSPACE_ASSISTANT_RELAY_ACTION_TIMEOUT_MS || 45000);
const ASSISTANT_RELAY_MAX_PENDING = Number(process.env.AI_WORKSPACE_ASSISTANT_RELAY_MAX_PENDING || 200);
const ASSISTANT_RELAY_MAX_BATCH = Number(process.env.AI_WORKSPACE_ASSISTANT_RELAY_MAX_BATCH || 10);

const config = readConfig();
const app = express();
const httpServer = createServer(app);
const wss = new WebSocketServer({ noServer: true });
const agentsByCode = new Map();
const assistantRelaysById = new Map();
let eventSeq = 0;

app.disable("x-powered-by");
app.use(express.json({ limit: "1mb" }));

app.get("/healthz", (_req, res) => {
  res.json({
    ok: true,
    service: "nodedc-ai-workspace-hub",
    wsPath: config.wsPath,
    agentsOnline: Array.from(agentsByCode.values()).filter(isAgentOnline).length,
    assistantRelays: assistantRelaysById.size,
    internalApiConfigured: config.internalAccessTokens.length > 0,
    ontologyMcpProxyConfigured: Boolean(config.ontologyCoreUrl && config.ontologyCoreAccessToken),
  });
});

app.get("/api/ai-workspace/hub/v1/agents/:pairingCode", requireInternalApi, (req, res) => {
  const agent = agentsByCode.get(cleanPairingCode(req.params.pairingCode));
  res.json({ ok: true, agent: publicAgent(agent) });
});

app.get("/api/ai-workspace/hub/v1/agents/:pairingCode/events", requireInternalApi, (req, res) => {
  const payload = readAgentEvents(req.params.pairingCode, {
    since: req.query.since,
    limit: req.query.limit,
  });
  res.json({ ok: true, ...payload });
});

app.post("/api/ai-workspace/hub/v1/agents/:pairingCode/request", requireInternalApi, asyncRoute(async (req, res) => {
  const command = cleanString(req.body?.command, 100);
  const timeoutMs = sanitizeTimeoutMs(req.body?.timeoutMs, 30000);
  const payload = await requestAgent(req.params.pairingCode, command, req.body?.payload || {}, timeoutMs, {
    quiet: Boolean(req.body?.quiet),
  });
  res.json({ ok: true, payload });
}));

app.post("/api/ai-workspace/hub/v1/agents/:pairingCode/dispatch", requireInternalApi, (req, res) => {
  const command = cleanString(req.body?.command, 100);
  const timeoutMs = sanitizeTimeoutMs(req.body?.timeoutMs, 30000);
  const dispatch = dispatchAgent(req.params.pairingCode, command, req.body?.payload || {}, timeoutMs, {
    quiet: Boolean(req.body?.quiet),
  });
  res.json({ ok: true, requestId: dispatch.requestId });
});

app.post("/api/ai-workspace/assistant/v1/actions", requireInternalApi, asyncRoute(proxyAssistantActions));
app.get("/api/ai-workspace/assistant/v1/executors", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/assistant/v1/executors", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/assistant/v1/executors/:executorId/agent/setup-command", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/assistant/v1/executors/:executorId/check", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/assistant/v1/threads", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.get("/api/ai-workspace/assistant/v1/threads/:threadId/messages", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/assistant/v1/threads/:threadId/messages", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/assistant/v1/threads/:threadId/dispatch", requireInternalApi, asyncRoute(proxyAssistantControlPlane));
app.post("/api/ai-workspace/setup-codes/redeem", asyncRoute(proxySetupCodeRedeem));
app.get("/api/ai-workspace/bridge-package.tgz", asyncRoute(proxyBridgePackage));

app.post("/api/ai-workspace/hub/v1/assistant-relays/:relayId/actions", requireInternalApi, asyncRoute(callAssistantRelayAction));
app.post("/api/ai-workspace/hub/v1/assistant-relays/:relayId/poll", requireInternalApi, asyncRoute(pollAssistantRelay));
app.post("/api/ai-workspace/hub/v1/assistant-relays/:relayId/results/:callId", requireInternalApi, asyncRoute(completeAssistantRelayCall));

app.use("/api/ai-workspace/hub/v1/ndc-agent-mcp/:pairingCode", asyncRoute(proxyNdcAgentMcp));
app.use("/api/ai-workspace/hub/v1/ontology-mcp/:pairingCode", asyncRoute(proxyOntologyMcp));

app.use((error, _req, res, _next) => {
  const status = Number(error?.status || 500);
  res.status(status >= 400 && status < 600 ? status : 500).json({
    ok: false,
    error: String(error?.message || error || "internal_error"),
  });
});

httpServer.on("upgrade", (req, socket, head) => {
  let pathname = "";
  try {
    pathname = new URL(req.url || "/", "http://localhost").pathname;
  } catch {}
  if (pathname !== config.wsPath) return;
  wss.handleUpgrade(req, socket, head, (ws) => {
    wss.emit("connection", ws, req);
  });
});

wss.on("connection", attachAgent);

const heartbeat = setInterval(() => {
  for (const agent of Array.from(agentsByCode.values())) {
    if (!isSocketOpen(agent) || isAgentStale(agent)) {
      removeAgent(agent, "bridge_agent_stale");
      continue;
    }
    try {
      agent.awaitingPong = true;
      agent.lastPingAt = new Date().toISOString();
      agent.socket.ping();
    } catch {
      removeAgent(agent, "bridge_agent_ping_failed");
    }
  }
}, HEARTBEAT_INTERVAL_MS);

httpServer.listen(config.port, "0.0.0.0", () => {
  console.log(`NODE.DC AI Workspace Hub listening on http://0.0.0.0:${config.port}`);
  console.log(`NODE.DC AI Workspace Hub ws path: ${config.wsPath}`);
});

process.on("SIGTERM", shutdown);
process.on("SIGINT", shutdown);

function attachAgent(socket, req) {
  const url = new URL(req.url || config.wsPath, "http://localhost");
  const pairingCode = cleanPairingCode(url.searchParams.get("pairingCode"));
  if (!pairingCode) {
    socket.close(1008, "pairing_code_required");
    return;
  }

  const previous = agentsByCode.get(pairingCode);
  if (previous) {
    removeAgent(previous, "agent_replaced");
  }

  const now = new Date().toISOString();
  const agent = {
    socket,
    pairingCode,
    machineName: cleanString(url.searchParams.get("machineName"), 120),
    host: "",
    agentVersion: "",
    protocolVersion: "",
    capabilities: [],
    runtimeStatus: "",
    runtimeError: "",
    runtimeCheckedAt: "",
    connectedAt: now,
    lastSeenAt: now,
    lastPingAt: "",
    awaitingPong: false,
    closed: false,
    pending: new Map(),
    requestMeta: previous?.requestMeta || new Map(),
    events: previous?.events || [],
  };
  agentsByCode.set(pairingCode, agent);
  pushAgentEvent(agent, "", { kind: "connected", message: "Bridge agent connected." });

  socket.on("pong", () => {
    agent.lastSeenAt = new Date().toISOString();
    agent.awaitingPong = false;
  });
  socket.on("message", (raw) => handleAgentMessage(agent, raw));
  socket.on("close", () => removeAgent(agent, "bridge_agent_offline"));
  socket.on("error", () => {});

  sendJson(socket, {
    type: "ready",
    pairingCode,
    connectedAt: now,
  });
}

function handleAgentMessage(agent, raw) {
  agent.lastSeenAt = new Date().toISOString();
  agent.awaitingPong = false;
  let message = null;
  try {
    message = JSON.parse(String(raw));
  } catch {
    return;
  }

  if (message?.type === "hello") {
    agent.machineName = cleanString(message.machineName || agent.machineName, 120);
    agent.host = cleanString(message.host, 120);
    agent.agentVersion = cleanString(message.agentVersion, 80);
    agent.protocolVersion = cleanString(message.protocolVersion, 120);
    agent.capabilities = cleanStringList(message.capabilities, 80, 80);
    agent.runtimeStatus = cleanString(message.runtimeStatus, 40);
    agent.runtimeError = cleanString(message.runtimeError, 1000);
    agent.runtimeCheckedAt = cleanString(message.runtimeCheckedAt, 80);
    pushAgentEvent(agent, "", {
      kind: "hello",
      message: "Bridge agent hello received.",
      cwd: cleanString(message.cwd, 500),
      agentVersion: agent.agentVersion,
      protocolVersion: agent.protocolVersion,
    });
    return;
  }

  if (message?.type === "event") {
    const pending = message?.requestId ? agent.pending.get(String(message.requestId || "")) : null;
    if (pending?.quiet) return;
    pushAgentEvent(agent, message.requestId, message.event || message.payload || {});
    return;
  }

  if (message?.type !== "response") return;
  const requestId = String(message.requestId || "");
  const pending = agent.pending.get(requestId);
  if (!pending) return;
  agent.pending.delete(requestId);
  clearTimeout(pending.timeout);
  if (!pending.quiet) {
    pushAgentEvent(agent, requestId, {
      kind: "response_received",
      message: `Bridge response received after ${elapsedLabel(pending.startedAt)}.`,
    });
  }
  if (message.ok === false) {
    const error = new Error(String(message.error || "bridge_agent_failed"));
    error.status = Number(message.status || 502);
    if (!pending.quiet) pushAgentEvent(agent, requestId, { kind: "error", message: error.message });
    pending.reject(error);
    return;
  }
  if (!pending.quiet) pushAgentEvent(agent, requestId, { kind: "done", message: "Bridge request completed." });
  pending.resolve(message.payload || { ok: true });
}

function requestAgent(pairingCodeRaw, command, payload = {}, timeoutMs = 30000, options = {}) {
  return startAgentRequest(pairingCodeRaw, command, payload, timeoutMs, options).promise;
}

function dispatchAgent(pairingCodeRaw, command, payload = {}, timeoutMs = 30000, options = {}) {
  const { requestId, promise } = startAgentRequest(pairingCodeRaw, command, payload, timeoutMs, options);
  promise.catch(() => {});
  return { requestId };
}

async function proxyNdcAgentMcp(req, res) {
  if (!config.engineInternalUrl || !config.engineInternalAccessToken) {
    res.status(503).json({ ok: false, error: "engine_proxy_not_configured" });
    return;
  }
  const pairingCode = cleanPairingCode(req.params.pairingCode);
  const agent = agentsByCode.get(pairingCode);
  if (!agent || !isAgentOnline(agent)) {
    res.status(503).json({ ok: false, error: "bridge_agent_offline" });
    return;
  }

  const marker = `/api/ai-workspace/hub/v1/ndc-agent-mcp/${encodeURIComponent(req.params.pairingCode)}`;
  const suffix = String(req.originalUrl || "").startsWith(marker)
    ? String(req.originalUrl || "").slice(marker.length)
    : String(req.url || "");
  const targetUrl = `${config.engineInternalUrl.replace(/\/+$/, "")}/api/ndc-agent-mcp${suffix || ""}`;
  const method = String(req.method || "GET").toUpperCase();
  const hasBody = !["GET", "HEAD"].includes(method);
  const upstream = await fetch(targetUrl, {
    method,
    redirect: "manual",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${config.engineInternalAccessToken}`,
      ...(hasBody ? { "Content-Type": "application/json" } : {}),
    },
    ...(hasBody ? { body: JSON.stringify(req.body || {}) } : {}),
  });
  const contentType = upstream.headers.get("content-type") || "application/json; charset=utf-8";
  const text = await upstream.text();
  res.status(upstream.status);
  res.setHeader("content-type", contentType);
  res.send(text);
}

async function proxyOntologyMcp(req, res) {
  if (!config.ontologyCoreUrl || !config.ontologyCoreAccessToken) {
    res.status(503).json({ ok: false, error: "ontology_mcp_proxy_not_configured" });
    return;
  }
  const pairingCode = cleanPairingCode(req.params.pairingCode);
  const agent = agentsByCode.get(pairingCode);
  if (!agent || !isAgentOnline(agent)) {
    res.status(503).json({ ok: false, error: "bridge_agent_offline" });
    return;
  }

  const marker = `/api/ai-workspace/hub/v1/ontology-mcp/${encodeURIComponent(req.params.pairingCode)}`;
  const suffix = String(req.originalUrl || "").startsWith(marker)
    ? String(req.originalUrl || "").slice(marker.length)
    : String(req.url || "");
  const targetUrl = `${config.ontologyCoreUrl.replace(/\/+$/, "")}${suffix || "/mcp"}`;
  await proxyInternalMcpRequest(req, res, targetUrl, config.ontologyCoreAccessToken);
}

async function proxyInternalMcpRequest(req, res, targetUrl, accessToken) {
  const method = String(req.method || "GET").toUpperCase();
  const hasBody = !["GET", "HEAD"].includes(method);
  const upstream = await fetch(targetUrl, {
    method,
    redirect: "manual",
    headers: {
      Accept: String(req.headers.accept || "application/json, text/event-stream"),
      Authorization: `Bearer ${accessToken}`,
      ...forwardMcpHeaders(req),
      ...(hasBody ? { "Content-Type": "application/json" } : {}),
    },
    ...(hasBody ? { body: JSON.stringify(req.body || {}) } : {}),
  });
  const contentType = upstream.headers.get("content-type") || "application/json; charset=utf-8";
  const text = await upstream.text();
  res.status(upstream.status);
  res.setHeader("content-type", contentType);
  for (const header of ["cache-control", "mcp-protocol-version", "mcp-session-id", "vary"]) {
    const value = upstream.headers.get(header);
    if (value) res.setHeader(header, value);
  }
  res.send(text);
}

function forwardMcpHeaders(req) {
  const headers = {};
  for (const name of ["mcp-protocol-version", "mcp-session-id", "last-event-id"]) {
    const value = cleanString(req.headers[name], 1000);
    if (value) headers[name] = value;
  }
  return headers;
}

async function proxyAssistantActions(req, res) {
  if (!config.assistantInternalUrl || !config.assistantInternalAccessToken) {
    res.status(503).json({ ok: false, error: "assistant_action_proxy_not_configured" });
    return;
  }
  const targetUrl = `${config.assistantInternalUrl.replace(/\/+$/, "")}/api/ai-workspace/assistant/v1/actions`;
  const upstream = await fetch(targetUrl, {
    method: "POST",
    redirect: "manual",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: `Bearer ${config.assistantInternalAccessToken}`,
      ...forwardOwnerHeaders(req),
    },
    body: JSON.stringify(req.body || {}),
  });
  const contentType = upstream.headers.get("content-type") || "application/json; charset=utf-8";
  const text = await upstream.text();
  res.status(upstream.status);
  res.setHeader("content-type", contentType);
  res.send(text);
}

async function proxyAssistantControlPlane(req, res) {
  if (!config.assistantInternalUrl || !config.assistantInternalAccessToken) {
    res.status(503).json({ ok: false, error: "assistant_control_plane_proxy_not_configured" });
    return;
  }

  const method = String(req.method || "GET").toUpperCase();
  const hasBody = !["GET", "HEAD"].includes(method);
  const targetUrl = `${config.assistantInternalUrl.replace(/\/+$/, "")}${String(req.originalUrl || req.url || "")}`;
  const upstream = await fetch(targetUrl, {
    method,
    redirect: "manual",
    headers: {
      Accept: "application/json",
      Authorization: `Bearer ${config.assistantInternalAccessToken}`,
      ...forwardOwnerHeaders(req),
      ...(hasBody ? { "Content-Type": "application/json" } : {}),
    },
    ...(hasBody ? { body: JSON.stringify(req.body || {}) } : {}),
  });
  const contentType = upstream.headers.get("content-type") || "application/json; charset=utf-8";
  const text = await upstream.text();
  res.status(upstream.status);
  res.setHeader("content-type", contentType);
  res.send(text);
}

async function proxySetupCodeRedeem(req, res) {
  if (!config.assistantInternalUrl || !config.assistantInternalAccessToken) {
    res.status(503).json({ ok: false, error: "assistant_setup_proxy_not_configured" });
    return;
  }
  const targetUrl = `${config.assistantInternalUrl.replace(/\/+$/, "")}/api/ai-workspace/assistant/v1/setup-codes/redeem`;
  const upstream = await fetch(targetUrl, {
    method: "POST",
    redirect: "manual",
    headers: {
      Accept: "application/json",
      "Content-Type": "application/json",
      Authorization: `Bearer ${config.assistantInternalAccessToken}`,
    },
    body: JSON.stringify(req.body || {}),
  });
  const contentType = upstream.headers.get("content-type") || "application/json; charset=utf-8";
  const text = await upstream.text();
  res.status(upstream.status);
  res.setHeader("content-type", contentType);
  res.send(text);
}

async function proxyBridgePackage(_req, res) {
  if (!config.assistantInternalUrl || !config.assistantInternalAccessToken) {
    res.status(503).json({ ok: false, error: "assistant_bridge_package_proxy_not_configured" });
    return;
  }
  const targetUrl = `${config.assistantInternalUrl.replace(/\/+$/, "")}/api/ai-workspace/assistant/v1/bridge-package.tgz`;
  const upstream = await fetch(targetUrl, {
    method: "GET",
    redirect: "manual",
    headers: {
      Accept: "application/octet-stream",
      Authorization: `Bearer ${config.assistantInternalAccessToken}`,
    },
  });
  const contentType = upstream.headers.get("content-type") || "application/octet-stream";
  const body = Buffer.from(await upstream.arrayBuffer());
  res.status(upstream.status);
  res.setHeader("content-type", contentType);
  for (const header of [
    "cache-control",
    "pragma",
    "expires",
    "surrogate-control",
    "content-disposition",
    "x-ai-workspace-bridge-package-sha256",
  ]) {
    const value = upstream.headers.get(header);
    if (value) res.setHeader(header, value);
  }
  res.send(body);
}

async function callAssistantRelayAction(req, res) {
  const relayId = cleanRelayId(req.params.relayId);
  if (!relayId) {
    res.status(400).json({ ok: false, error: "assistant_relay_id_required" });
    return;
  }

  const relay = getAssistantRelay(relayId);
  pruneAssistantRelay(relay);
  if (relay.calls.size >= ASSISTANT_RELAY_MAX_PENDING) {
    res.status(429).json({ ok: false, error: "assistant_relay_backpressure" });
    return;
  }

  const callId = crypto.randomUUID();
  const timeoutMs = sanitizeTimeoutMs(req.body?.timeoutMs || req.query?.timeoutMs || ASSISTANT_RELAY_ACTION_TIMEOUT_MS, ASSISTANT_RELAY_ACTION_TIMEOUT_MS);
  const createdAt = new Date().toISOString();
  const call = {
    callId,
    relayId,
    createdAt,
    payload: req.body || {},
    headers: forwardOwnerHeaders(req),
  };

  const result = await new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      relay.calls.delete(callId);
      relay.pending = relay.pending.filter((item) => item.callId !== callId);
      const error = new Error("assistant_relay_timeout");
      error.status = 504;
      reject(error);
    }, timeoutMs);
    timeout.unref?.();
    relay.calls.set(callId, { resolve, reject, timeout, createdAt: Date.now() });
    relay.pending.push(call);
    notifyAssistantRelayWaiters(relay);
  });

  res.status(result.status).json(result.body);
}

async function pollAssistantRelay(req, res) {
  const relayId = cleanRelayId(req.params.relayId);
  if (!relayId) {
    res.status(400).json({ ok: false, error: "assistant_relay_id_required" });
    return;
  }
  const relay = getAssistantRelay(relayId);
  relay.lastSeenAt = new Date().toISOString();
  const limit = sanitizeInteger(req.body?.limit, ASSISTANT_RELAY_MAX_BATCH, 1, ASSISTANT_RELAY_MAX_BATCH);
  const timeoutMs = sanitizeTimeoutMs(req.body?.timeoutMs || req.query?.timeoutMs || ASSISTANT_RELAY_POLL_TIMEOUT_MS, ASSISTANT_RELAY_POLL_TIMEOUT_MS);
  const calls = await waitForAssistantRelayCalls(relay, limit, timeoutMs);
  res.json({ ok: true, relayId, calls });
}

async function completeAssistantRelayCall(req, res) {
  const relayId = cleanRelayId(req.params.relayId);
  const callId = cleanString(req.params.callId, 120);
  const relay = assistantRelaysById.get(relayId);
  const pending = relay?.calls.get(callId);
  if (!relay || !pending) {
    res.status(404).json({ ok: false, error: "assistant_relay_call_not_found" });
    return;
  }

  relay.calls.delete(callId);
  clearTimeout(pending.timeout);
  pending.resolve({
    status: sanitizeHttpStatus(req.body?.status),
    body: req.body?.body === undefined ? { ok: true } : req.body.body,
  });
  res.json({ ok: true, relayId, callId });
}

function getAssistantRelay(relayId) {
  const cleanId = cleanRelayId(relayId);
  let relay = assistantRelaysById.get(cleanId);
  if (!relay) {
    relay = {
      relayId: cleanId,
      pending: [],
      waiters: [],
      calls: new Map(),
      createdAt: new Date().toISOString(),
      lastSeenAt: "",
    };
    assistantRelaysById.set(cleanId, relay);
  }
  return relay;
}

function waitForAssistantRelayCalls(relay, limit, timeoutMs) {
  const ready = takeAssistantRelayCalls(relay, limit);
  if (ready.length) return Promise.resolve(ready);
  return new Promise((resolve) => {
    const timeout = setTimeout(() => {
      relay.waiters = relay.waiters.filter((waiter) => waiter.resolve !== resolve);
      resolve([]);
    }, timeoutMs);
    timeout.unref?.();
    relay.waiters.push({ resolve, timeout, limit });
  });
}

function notifyAssistantRelayWaiters(relay) {
  while (relay.waiters.length && relay.pending.length) {
    const waiter = relay.waiters.shift();
    clearTimeout(waiter.timeout);
    waiter.resolve(takeAssistantRelayCalls(relay, waiter.limit));
  }
}

function takeAssistantRelayCalls(relay, limit) {
  const calls = [];
  while (relay.pending.length && calls.length < limit) {
    const call = relay.pending.shift();
    if (relay.calls.has(call.callId)) calls.push(call);
  }
  return calls;
}

function pruneAssistantRelay(relay) {
  relay.pending = relay.pending.filter((call) => relay.calls.has(call.callId));
}

function cleanRelayId(value) {
  return String(value || "").trim().replace(/[^A-Za-z0-9_.:-]/g, "").slice(0, 120);
}

function sanitizeHttpStatus(value) {
  const status = Number(value || 200);
  return Number.isInteger(status) && status >= 100 && status <= 599 ? status : 200;
}

function forwardOwnerHeaders(req) {
  const headers = {};
  for (const name of [
    "x-nodedc-user-id",
    "x-nodedc-user-email",
    "x-nodedc-user-role",
    "x-nodedc-user-groups",
  ]) {
    const value = req.headers[name];
    if (typeof value === "string" && value.trim()) headers[name] = value.trim();
  }
  return headers;
}

function startAgentRequest(pairingCodeRaw, command, payload = {}, timeoutMs = 30000, options = {}) {
  const pairingCode = cleanPairingCode(pairingCodeRaw);
  const agent = agentsByCode.get(pairingCode);
  if (!agent || !isAgentOnline(agent)) {
    const error = new Error("bridge_agent_offline");
    error.status = 503;
    throw error;
  }

  const requestId = crypto.randomUUID();
  const quiet = Boolean(options?.quiet);
  agent.requestMeta.set(requestId, requestMetaFromPayload(command, payload));
  trimRequestMeta(agent);
  const promise = new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      agent.pending.delete(requestId);
      const error = new Error("bridge_timeout");
      error.status = 504;
      if (!quiet) pushAgentEvent(agent, requestId, { kind: "timeout", command, message: "Bridge request timed out." });
      reject(error);
    }, timeoutMs);
    const startedAt = Date.now();
    agent.pending.set(requestId, { resolve, reject, timeout, startedAt, quiet });
    if (!quiet) pushAgentEvent(agent, requestId, { kind: "engine_send", command, message: `Engine sent request: ${command}` });
    sendJson(agent.socket, {
      type: "request",
      requestId,
      command: String(command || ""),
      payload,
      quiet,
    });
  });
  return { requestId, promise };
}

function readAgentEvents(pairingCodeRaw, options = {}) {
  const pairingCode = cleanPairingCode(pairingCodeRaw);
  const agent = agentsByCode.get(pairingCode);
  const since = Number(options.since || 0);
  const limit = Math.max(0, Math.min(2000, Number(options.limit || 100)));
  const events = agent?.events || [];
  const latestEventId = events.length ? events[events.length - 1].id : eventSeq;
  return {
    events: events.filter((event) => event.id > since).slice(-limit),
    latestEventId,
    online: Boolean(agent && isAgentOnline(agent)),
  };
}

function requestMetaFromPayload(command, payload = {}) {
  const context = payload?.context && typeof payload.context === "object" ? payload.context : {};
  const publicUserMessage = payload?.displayMessage || payload?.publicUserMessage || payload?.message;
  return {
    command: cleanString(command, 80),
    threadId: cleanString(payload?.threadId, 160),
    threadTitle: cleanString(payload?.threadTitle, 240),
    userMessage: cleanString(publicUserMessage, 12000),
    remoteControlMode: cleanString(context.remoteControlMode, 40),
  };
}

function pushAgentEvent(agent, requestId, rawEvent = {}) {
  if (!agent) return null;
  const now = new Date().toISOString();
  const cleanRequestId = String(requestId || rawEvent.requestId || "");
  const meta = cleanRequestId ? agent.requestMeta?.get(cleanRequestId) : null;
  const kind = cleanString(rawEvent.kind || rawEvent.type || "event", 40);
  const eventTextMax = kind === "codex_message" ? CODEX_MESSAGE_EVENT_TEXT_MAX : DEFAULT_AGENT_EVENT_TEXT_MAX;
  const event = {
    id: ++eventSeq,
    pairingCode: agent.pairingCode,
    requestId: cleanRequestId,
    threadId: rawEvent.threadId == null ? cleanString(meta?.threadId, 160) : cleanString(rawEvent.threadId, 160),
    sessionId: rawEvent.sessionId == null ? "" : cleanString(rawEvent.sessionId, 160),
    threadTitle: rawEvent.threadTitle == null ? cleanString(meta?.threadTitle, 240) : cleanString(rawEvent.threadTitle, 240),
    userMessage: rawEvent.userMessage == null ? cleanString(meta?.userMessage, 12000) : cleanString(rawEvent.userMessage, 12000),
    remoteControlMode: rawEvent.remoteControlMode == null ? cleanString(meta?.remoteControlMode, 40) : cleanString(rawEvent.remoteControlMode, 40),
    kind,
    stream: rawEvent.stream ? cleanString(rawEvent.stream, 40) : "",
    text: rawEvent.text == null ? "" : cleanString(rawEvent.text, eventTextMax),
    message: rawEvent.message == null ? "" : cleanString(rawEvent.message, eventTextMax),
    command: rawEvent.command == null ? "" : cleanString(rawEvent.command, 1000),
    cwd: rawEvent.cwd == null ? "" : cleanString(rawEvent.cwd, 500),
    currentFile: rawEvent.currentFile == null ? "" : cleanString(rawEvent.currentFile, 1000),
    eventsFile: rawEvent.eventsFile == null ? "" : cleanString(rawEvent.eventsFile, 1000),
    at: rawEvent.at ? cleanString(rawEvent.at, 80) : now,
  };
  agent.events.push(event);
  if (agent.events.length > MAX_EVENTS_PER_AGENT) {
    agent.events.splice(0, agent.events.length - MAX_EVENTS_PER_AGENT);
  }
  return event;
}

function publicAgent(agent) {
  if (!agent) return null;
  return {
    online: isAgentOnline(agent),
    pairingCode: agent.pairingCode,
    machineName: agent.machineName,
    host: agent.host,
    agentVersion: agent.agentVersion,
    protocolVersion: agent.protocolVersion,
    capabilities: agent.capabilities,
    runtimeStatus: agent.runtimeStatus,
    runtimeError: agent.runtimeError,
    runtimeCheckedAt: agent.runtimeCheckedAt,
    connectedAt: agent.connectedAt,
    lastSeenAt: agent.lastSeenAt,
  };
}

function isSocketOpen(agent) {
  return Boolean(agent?.socket && agent.socket.readyState === WebSocket.OPEN);
}

function isAgentStale(agent) {
  const lastSeenMs = Date.parse(agent?.lastSeenAt || agent?.connectedAt || "");
  if (!Number.isFinite(lastSeenMs)) return true;
  return Date.now() - lastSeenMs > AGENT_STALE_MS;
}

function isAgentOnline(agent) {
  return isSocketOpen(agent) && !isAgentStale(agent);
}

function removeAgent(agent, reason = "bridge_agent_offline") {
  if (!agent || agent.closed) return;
  agent.closed = true;
  const error = Object.assign(new Error(reason), { status: reason === "agent_replaced" ? 409 : 503 });
  pushAgentEvent(agent, "", {
    kind: "disconnected",
    message: reason === "agent_replaced"
      ? "Bridge agent connection replaced."
      : reason === "bridge_agent_stale"
        ? "Bridge agent heartbeat timed out."
        : "Bridge agent disconnected.",
  });
  if (agentsByCode.get(agent.pairingCode) === agent) agentsByCode.delete(agent.pairingCode);
  settleAll(agent, error);
  try {
    if (isSocketOpen(agent)) agent.socket.terminate();
  } catch {}
}

function settleAll(agent, error) {
  for (const pending of agent.pending.values()) {
    clearTimeout(pending.timeout);
    pending.reject(error);
  }
  agent.pending.clear();
}

function trimRequestMeta(agent) {
  if (!agent?.requestMeta || agent.requestMeta.size <= MAX_REQUEST_META_PER_AGENT) return;
  const excess = agent.requestMeta.size - MAX_REQUEST_META_PER_AGENT;
  Array.from(agent.requestMeta.keys()).slice(0, excess).forEach((key) => agent.requestMeta.delete(key));
}

function sendJson(socket, payload) {
  socket.send(JSON.stringify(payload));
}

function cleanPairingCode(value) {
  return String(value || "")
    .trim()
    .toUpperCase()
    .replace(/[^A-Z0-9]/g, "")
    .slice(0, 32);
}

function cleanString(value, maxLength) {
  return String(value || "").trim().slice(0, maxLength);
}

function cleanStringList(value, maxItems = 80, maxLength = 120) {
  const source = Array.isArray(value)
    ? value
    : String(value || "").split(/[\n,;]+/);
  const out = [];
  for (const item of source) {
    const text = cleanString(item, maxLength);
    if (!text || out.includes(text)) continue;
    out.push(text);
    if (out.length >= maxItems) break;
  }
  return out;
}

function sanitizeTimeoutMs(value, fallback) {
  const numeric = Number(value || fallback);
  if (!Number.isFinite(numeric)) return fallback;
  return Math.max(1000, Math.min(12 * 60 * 60 * 1000, numeric));
}

function sanitizeInteger(value, fallback, min, max) {
  const numeric = Number(value || fallback);
  if (!Number.isFinite(numeric)) return fallback;
  return Math.min(Math.max(Math.trunc(numeric), min), max);
}

function elapsedLabel(startedAt) {
  const elapsed = Math.max(0, Date.now() - Number(startedAt || Date.now()));
  if (elapsed < 1000) return `${elapsed}ms`;
  return `${(elapsed / 1000).toFixed(1)}s`;
}

function asyncRoute(handler) {
  return (req, res, next) => Promise.resolve(handler(req, res, next)).catch(next);
}

function requireInternalApi(req, res, next) {
  if (!config.internalAccessTokens.length) {
    res.status(503).json({ ok: false, error: "ai_workspace_hub_token_not_configured" });
    return;
  }
  const header = String(req.headers.authorization || "");
  const token = header.startsWith("Bearer ") ? header.slice(7) : "";
  if (!token || !config.internalAccessTokens.some((candidate) => safeEqual(token, candidate))) {
    res.status(401).json({ ok: false, error: "ai_workspace_hub_unauthorized" });
    return;
  }
  next();
}

function safeEqual(left, right) {
  const leftBuffer = Buffer.from(String(left || ""));
  const rightBuffer = Buffer.from(String(right || ""));
  return leftBuffer.length === rightBuffer.length && crypto.timingSafeEqual(leftBuffer, rightBuffer);
}

function readConfig() {
  const internalAccessTokens = Array.from(new Set([
    process.env.AI_WORKSPACE_HUB_TOKEN,
    process.env.NODEDC_INTERNAL_ACCESS_TOKEN,
  ].map((value) => cleanString(value, 1000)).filter(Boolean)));
  return {
    port: Number(process.env.PORT || 18081),
    wsPath: process.env.AI_WORKSPACE_HUB_WS_PATH || DEFAULT_WS_PATH,
    internalAccessTokens,
    engineInternalUrl: cleanString(process.env.NODEDC_ENGINE_INTERNAL_URL, 1000).replace(/\/+$/, ""),
    engineInternalAccessToken: cleanString(process.env.NODEDC_INTERNAL_ACCESS_TOKEN, 1000),
    assistantInternalUrl: cleanString(
      process.env.NODEDC_AI_WORKSPACE_ASSISTANT_URL ||
      process.env.NDC_AI_WORKSPACE_ASSISTANT_INTERNAL_URL ||
      process.env.AI_WORKSPACE_ASSISTANT_INTERNAL_URL ||
      "http://ai-workspace-assistant:18082",
      1000,
    ).replace(/\/+$/, ""),
    assistantInternalAccessToken: cleanString(process.env.NODEDC_INTERNAL_ACCESS_TOKEN, 1000),
    ontologyCoreUrl: cleanString(
      process.env.NODEDC_ONTOLOGY_CORE_URL ||
      process.env.NDC_ONTOLOGY_CORE_URL ||
      "http://ontology-core:18104",
      1000,
    ).replace(/\/+$/, ""),
    ontologyCoreAccessToken: cleanString(process.env.NODEDC_INTERNAL_ACCESS_TOKEN, 1000),
  };
}

function shutdown() {
  clearInterval(heartbeat);
  wss.close();
  httpServer.close(() => {
    process.exit(0);
  });
  setTimeout(() => process.exit(1), 5000).unref();
}
