import { getLogger } from "../logger.js";
import { createMiddleware } from "hono/factory";
import { context, propagation } from "@opentelemetry/api";

//#region src/middleware/tracing.ts
const logger = getLogger("tracing-middleware");
const otelBaggageMiddleware = () => createMiddleware(async (c, next) => {
	const reqId = c.get("requestId");
	let bag = propagation.getBaggage(context.active());
	if (!bag) bag = propagation.createBaggage();
	if (bag && typeof bag.setEntry === "function") {
		bag = bag.setEntry("request.id", { value: String(reqId ?? "unknown") });
		const ctxWithBag = propagation.setBaggage(context.active(), bag);
		return await context.with(ctxWithBag, async () => await next());
	}
	return next();
});
const executionBaggageMiddleware = () => createMiddleware(async (c, next) => {
	const executionContext = c.get("executionContext");
	if (!executionContext) {
		logger.debug({}, "Empty execution context");
		return next();
	}
	const { tenantId, projectId, agentId } = executionContext;
	let conversationId;
	const requestBody = c.get("requestBody") || {};
	if (requestBody) {
		conversationId = requestBody.conversationId;
		if (!conversationId) logger.debug({ requestBody }, "No conversation ID found in request body");
	}
	const entries = Object.fromEntries(Object.entries({
		"agent.id": agentId,
		"tenant.id": tenantId,
		"project.id": projectId,
		"conversation.id": conversationId
	}).filter((entry) => {
		const [, v] = entry;
		return typeof v === "string" && v.length > 0;
	}));
	if (!Object.keys(entries).length) {
		logger.debug({}, "Empty entries for baggage");
		return next();
	}
	const bag = Object.entries(entries).reduce((b, [key, value]) => b.setEntry(key, { value: value || "" }), propagation.getBaggage(context.active()) ?? propagation.createBaggage());
	const ctxWithBag = propagation.setBaggage(context.active(), bag);
	return await context.with(ctxWithBag, async () => await next());
});

//#endregion
export { executionBaggageMiddleware, otelBaggageMiddleware };