import { createServer } from "node:http";
//#region src/media-shared/http/test-helpers/mock-server.ts
/**
* In-process HTTP mock server for voice / media-understanding tests.
*
* DECISION (per docs/voice-rearchitecture.md §14):
*  - Tests must NOT hit real provider endpoints. We spin up an ephemeral HTTP
*    server (random port on 127.0.0.1) and assert request/response shapes.
*  - SSRF tests intentionally bind to 127.0.0.1 (private). Tests that exercise
*    the SSRF guard pass `allowPrivateNetwork: true` to the production code.
*  - This helper is import-only from `__tests__/` files — never from runtime
*    code. Kept under the runtime tree (not test/) so vitest picks it up via
*    the existing co-located test discovery.
*/
async function readRequestBody(req) {
	const chunks = [];
	for await (const chunk of req) chunks.push(chunk);
	return Buffer.concat(chunks);
}
async function writeResponse(res, spec) {
	if (spec.delayMs && spec.delayMs > 0) await new Promise((resolve) => setTimeout(resolve, spec.delayMs));
	const status = spec.status ?? 200;
	const headers = spec.headers ?? {};
	res.writeHead(status, headers);
	const body = spec.body;
	if (body === void 0) {
		res.end();
		return;
	}
	if (typeof body === "string" || Buffer.isBuffer(body)) {
		res.end(body);
		return;
	}
	for await (const chunk of body) if (!res.write(chunk)) await new Promise((resolve) => res.once("drain", resolve));
	res.end();
}
/**
* Start an HTTP mock server bound to 127.0.0.1 on an ephemeral port. The
* returned handle exposes the base URL, recorded requests, and a `close()`
* method tests should call in `afterEach` / `afterAll`.
*/
async function startMockServer(initialHandler) {
	const requests = [];
	let activeHandler = initialHandler;
	const server = createServer((req, res) => {
		(async () => {
			const body = await readRequestBody(req);
			requests.push({
				method: req.method ?? "GET",
				path: req.url ?? "/",
				headers: req.headers,
				body,
				receivedAt: Date.now()
			});
			try {
				await writeResponse(res, await activeHandler(req, body));
			} catch (error) {
				if (!res.headersSent) res.writeHead(500, { "content-type": "application/json" });
				res.end(JSON.stringify({ error: { message: String(error) } }));
			}
		})();
	});
	await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
	return {
		baseUrl: `http://127.0.0.1:${server.address().port}`,
		requests,
		setHandler(next) {
			activeHandler = next;
		},
		async close() {
			await new Promise((resolve, reject) => server.close((err) => err ? reject(err) : resolve()));
		}
	};
}
/**
* Convenience builder: cycle through a fixed sequence of responses (used by
* key-rotation tests where call N gets 401 and call N+1 gets 200).
*/
function cycleHandlers(specs) {
	let index = 0;
	return () => {
		const spec = specs[Math.min(index, specs.length - 1)];
		index += 1;
		return spec;
	};
}
//#endregion
export { cycleHandlers, startMockServer };

//# sourceMappingURL=mock-server.js.map