import { getLogger as getLogger$1 } from "./logger.js";
import { env } from "./env.js";
import { evalRoutes } from "./domains/evals/index.js";
import { workflowRoutes } from "./domains/evals/workflow/routes.js";
import { sessionAuth, sessionContext } from "./middleware/sessionAuth.js";
import { flushBatchProcessor } from "./instrumentation.js";
import { manageRoutes } from "./domains/manage/index.js";
import mcp_default from "./domains/mcp/routes/mcp.js";
import { runRoutes } from "./domains/run/index.js";
import { authCorsConfig, defaultCorsConfig, playgroundCorsConfig, runCorsConfig, signozCorsConfig } from "./middleware/cors.js";
import { errorHandler } from "./middleware/errorHandler.js";
import { manageApiKeyAuth } from "./middleware/manageAuth.js";
import { manageRefMiddleware, oauthRefMiddleware, runRefMiddleware, writeProtectionMiddleware } from "./middleware/ref.js";
import { runApiKeyAuth, runApiKeyAuthExcept } from "./middleware/runAuth.js";
import { requireTenantAccess } from "./middleware/tenantAccess.js";
import "./middleware/index.js";
import { branchScopedDbMiddleware } from "./middleware/branchScopedDb.js";
import { evalApiKeyAuth } from "./middleware/evalsAuth.js";
import { projectConfigMiddleware, projectConfigMiddlewareExcept } from "./middleware/projectConfig.js";
import { executionBaggageMiddleware } from "./middleware/tracing.js";
import { setupOpenAPIRoutes } from "./openapi.js";
import { healthChecksHandler } from "./routes/healthChecks.js";
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { OrgRoles } from "@inkeep/agents-core";
import { githubRoutes } from "@inkeep/agents-work-apps/github";
import { Hono } from "hono";
import { cors } from "hono/cors";
import { requestId } from "hono/request-id";
import { pinoLogger } from "hono-pino";

//#region src/createApp.ts
const logger = getLogger$1("agents-api");
const isTestEnvironment = () => env.ENVIRONMENT === "test";
const isWebhookRoute = (path) => {
	return path.includes("/triggers/") && !path.endsWith("/triggers") && !path.endsWith("/triggers/");
};
function createAgentsHono(config) {
	const { serverConfig, credentialStores, auth, sandboxConfig } = config;
	const app = new OpenAPIHono();
	const CapabilitiesResponseSchema = z.object({ sandbox: z.object({
		configured: z.boolean().describe("Whether a sandbox provider is configured. Required for Function Tools execution."),
		provider: z.enum(["native", "vercel"]).optional().describe("The configured sandbox provider, if enabled."),
		runtime: z.enum(["node22", "typescript"]).optional().describe("The configured sandbox runtime, if enabled.")
	}).describe("Sandbox execution capabilities (used by Function Tools).") }).describe("Optional server capabilities and configuration.").openapi("CapabilitiesResponseSchema");
	app.use("*", requestId());
	if (auth) {
		app.use("/api/auth/*", cors(authCorsConfig));
		app.on(["POST", "GET"], "/api/auth/*", (c) => {
			return auth.handler(c.req.raw);
		});
	}
	app.use("/run/*", cors(runCorsConfig));
	app.use("/manage/tenants/*/playground/token", cors(playgroundCorsConfig));
	app.use("/manage/tenants/*/signoz/*", cors(signozCorsConfig));
	app.use("*", async (c, next) => {
		if (auth && c.req.path.startsWith("/api/auth/")) return next();
		if (c.req.path.startsWith("/run/")) return next();
		if (c.req.path.includes("/playground/token")) return next();
		if (c.req.path.includes("/signoz/")) return next();
		if (c.req.path.includes("/work-apps/github/")) return next();
		return cors(defaultCorsConfig)(c, next);
	});
	app.use("*", async (c, next) => {
		c.set("serverConfig", serverConfig);
		c.set("credentialStores", credentialStores);
		await next();
	});
	app.use("/manage/*", async (c, next) => {
		c.set("auth", auth);
		await next();
	});
	app.use("/run/*", async (c, next) => {
		if (sandboxConfig) c.set("sandboxConfig", sandboxConfig);
		await next();
	});
	app.use("/run/*", async (c, next) => {
		if (c.req.header("content-type")?.includes("application/json")) try {
			const body = await c.req.json();
			c.set("requestBody", body);
		} catch (error) {
			logger.debug({ error }, "Failed to parse JSON body, continuing without parsed body");
		}
		return next();
	});
	app.use(pinoLogger({
		pino: getLogger$1("agents-api").getPinoInstance(),
		http: { onResLevel(c) {
			if (c.res.status >= 500) return "error";
			if (c.req.path.includes("/signoz/")) return "debug";
			return "info";
		} }
	}));
	app.onError(errorHandler);
	app.use("*", sessionContext());
	app.route("/", healthChecksHandler);
	app.openapi(createRoute({
		method: "get",
		path: "/api/workflow/process",
		tags: ["Workflows"],
		summary: "Process workflow jobs",
		description: "Keeps the workflow worker active to process queued jobs (called by cron)",
		responses: { 200: { description: "Processing complete" } }
	}), async (c) => {
		await new Promise((resolve) => setTimeout(resolve, 5e4));
		return c.json({
			processed: true,
			timestamp: (/* @__PURE__ */ new Date()).toISOString()
		});
	});
	app.use("/manage/tenants/*", async (c, next) => {
		if (isTestEnvironment()) {
			await next();
			return;
		}
		if (c.req.header("Authorization")?.startsWith("Bearer ")) return manageApiKeyAuth()(c, next);
		return sessionAuth()(c, next);
	});
	app.use("/manage/capabilities", async (c, next) => {
		if (!auth || isTestEnvironment()) {
			await next();
			return;
		}
		if (c.req.header("Authorization")?.startsWith("Bearer ")) return manageApiKeyAuth()(c, next);
		return sessionAuth()(c, next);
	});
	app.openapi(createRoute({
		method: "get",
		path: "/manage/capabilities",
		operationId: "capabilities",
		summary: "Get server capabilities",
		description: "Get information about optional server-side capabilities and configuration.",
		responses: { 200: {
			description: "Server capabilities",
			content: { "application/json": { schema: CapabilitiesResponseSchema } }
		} }
	}), (c) => {
		if (!sandboxConfig) return c.json({ sandbox: { configured: false } });
		return c.json({ sandbox: {
			configured: true,
			provider: sandboxConfig.provider,
			runtime: sandboxConfig.runtime
		} });
	});
	if (isTestEnvironment()) app.use("/manage/tenants/:tenantId/*", async (c, next) => {
		const tenantId = c.req.param("tenantId");
		if (tenantId) {
			c.set("tenantId", tenantId);
			c.set("userId", "anonymous");
			c.set("tenantRole", OrgRoles.OWNER);
		}
		await next();
	});
	else app.use("/manage/tenants/:tenantId/*", requireTenantAccess());
	app.use("/run/tenants/*", runApiKeyAuthExcept(isWebhookRoute));
	app.use("/run/agents/*", runApiKeyAuth());
	app.use("/run/v1/*", runApiKeyAuth());
	app.use("/run/api/*", runApiKeyAuth());
	app.use("/evals/tenants/*", evalApiKeyAuth());
	app.use("/manage/tenants/*", async (c, next) => manageRefMiddleware(c, next));
	app.use("/manage/tenants/*", (c, next) => writeProtectionMiddleware(c, next));
	app.use("/manage/tenants/*", async (c, next) => branchScopedDbMiddleware(c, next));
	app.use("/manage/oauth/login", async (c, next) => oauthRefMiddleware(c, next));
	app.use("/manage/oauth/login", async (c, next) => branchScopedDbMiddleware(c, next));
	app.use("/run/*", async (c, next) => runRefMiddleware(c, next));
	app.use("/run/tenants/*", projectConfigMiddlewareExcept(isWebhookRoute));
	app.use("/run/agents/*", projectConfigMiddleware);
	app.use("/run/v1/*", projectConfigMiddleware);
	app.use("/run/api/*", projectConfigMiddleware);
	app.use("/run/*", async (c, next) => {
		return executionBaggageMiddleware()(c, next);
	});
	app.route("/manage", manageRoutes);
	app.route("/run", runRoutes);
	app.route("/.well-known", workflowRoutes);
	app.post("/index", async (c) => {
		const originalUrl = new URL(c.req.url);
		const bodyBuffer = await c.req.arrayBuffer();
		const targetUrl = new URL("/.well-known/workflow/v1/flow", originalUrl.origin);
		const forwardedRequest = new Request(targetUrl.toString(), {
			method: "POST",
			headers: new Headers(c.req.raw.headers),
			body: bodyBuffer
		});
		return fetch(forwardedRequest);
	});
	app.route("/evals", evalRoutes);
	app.route("/work-apps/github", githubRoutes);
	app.route("/mcp", mcp_default);
	setupOpenAPIRoutes(app);
	app.use("/run/*", async (_c, next) => {
		await next();
		await flushBatchProcessor();
	});
	const base = new Hono();
	base.route("/", app);
	return base;
}

//#endregion
export { createAgentsHono, isWebhookRoute };