import { getLogger as getLogger$1 } from "../../../logger.js";
import { env } from "../../../env.js";
import runDbClient_default from "../../../data/db/runDbClient.js";
import { requireProjectPermission } from "../../../middleware/projectAccess.js";
import { speakeasyOffsetLimitPagination } from "../../../utils/speakeasy.js";
import { OpenAPIHono, createRoute, z } from "@hono/zod-openapi";
import { PaginationQueryParamsSchema, TenantProjectAgentIdParamsSchema, TenantProjectAgentParamsSchema, TriggerApiInsertSchema, TriggerApiUpdateSchema, TriggerInvocationListResponse, TriggerInvocationResponse, TriggerInvocationStatusEnum, TriggerWithWebhookUrlListResponse, TriggerWithWebhookUrlResponse, commonGetErrorResponses, createApiError, createTrigger, deleteTrigger, generateId, getCredentialReference, getTriggerById, getTriggerInvocationById, hashAuthenticationHeaders, listTriggerInvocationsPaginated, listTriggersPaginated, updateTrigger } from "@inkeep/agents-core";

//#region src/domains/manage/routes/triggers.ts
const logger = getLogger$1("triggers");
const app = new OpenAPIHono();
app.use("/", async (c, next) => {
	if (c.req.method === "POST") return requireProjectPermission("edit")(c, next);
	return next();
});
app.use("/:id", async (c, next) => {
	if (c.req.method === "PATCH") return requireProjectPermission("edit")(c, next);
	if (c.req.method === "DELETE") return requireProjectPermission("edit")(c, next);
	return next();
});
/**
* Generate webhook URL for a trigger
*/
function generateWebhookUrl(params) {
	const { baseUrl, tenantId, projectId, agentId, triggerId } = params;
	return `${baseUrl}/run/tenants/${tenantId}/projects/${projectId}/agents/${agentId}/triggers/${triggerId}`;
}
/**
* List Triggers for an Agent
*/
app.openapi(createRoute({
	method: "get",
	path: "/",
	summary: "List Triggers",
	operationId: "list-triggers",
	tags: ["Triggers"],
	request: {
		params: TenantProjectAgentParamsSchema,
		query: PaginationQueryParamsSchema
	},
	responses: {
		200: {
			description: "List of triggers retrieved successfully",
			content: { "application/json": { schema: TriggerWithWebhookUrlListResponse } }
		},
		...commonGetErrorResponses
	},
	...speakeasyOffsetLimitPagination
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, agentId } = c.req.valid("param");
	const { page, limit } = c.req.valid("query");
	const apiBaseUrl = env.INKEEP_AGENTS_API_URL;
	const result = await listTriggersPaginated(db)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		pagination: {
			page,
			limit
		}
	});
	const dataWithWebhookUrl = result.data.map((trigger) => {
		const { tenantId: _tid, projectId: _pid, agentId: _aid, ...triggerWithoutScopes } = trigger;
		return {
			...triggerWithoutScopes,
			webhookUrl: generateWebhookUrl({
				baseUrl: apiBaseUrl,
				tenantId,
				projectId,
				agentId,
				triggerId: trigger.id
			})
		};
	});
	return c.json({
		data: dataWithWebhookUrl,
		pagination: result.pagination
	});
});
/**
* Get Trigger by ID
*/
app.openapi(createRoute({
	method: "get",
	path: "/{id}",
	summary: "Get Trigger",
	operationId: "get-trigger-by-id",
	tags: ["Triggers"],
	request: { params: TenantProjectAgentIdParamsSchema },
	responses: {
		200: {
			description: "Trigger found",
			content: { "application/json": { schema: TriggerWithWebhookUrlResponse } }
		},
		...commonGetErrorResponses
	}
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, agentId, id } = c.req.valid("param");
	const apiBaseUrl = env.INKEEP_AGENTS_API_URL;
	const trigger = await getTriggerById(db)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		triggerId: id
	});
	if (!trigger) throw createApiError({
		code: "not_found",
		message: "Trigger not found"
	});
	const { tenantId: _tid, projectId: _pid, agentId: _aid, ...triggerWithoutScopes } = trigger;
	return c.json({ data: {
		...triggerWithoutScopes,
		webhookUrl: generateWebhookUrl({
			baseUrl: apiBaseUrl,
			tenantId,
			projectId,
			agentId,
			triggerId: trigger.id
		})
	} });
});
/**
* Create Trigger
*/
app.openapi(createRoute({
	method: "post",
	path: "/",
	summary: "Create Trigger",
	operationId: "create-trigger",
	tags: ["Triggers"],
	request: {
		params: TenantProjectAgentParamsSchema,
		body: { content: { "application/json": { schema: TriggerApiInsertSchema } } }
	},
	responses: {
		201: {
			description: "Trigger created successfully",
			content: { "application/json": { schema: TriggerWithWebhookUrlResponse } }
		},
		...commonGetErrorResponses
	}
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, agentId } = c.req.valid("param");
	const body = c.req.valid("json");
	const apiBaseUrl = env.INKEEP_AGENTS_API_URL;
	const id = body.id || generateId();
	logger.debug({
		tenantId,
		projectId,
		agentId,
		triggerId: id
	}, "Creating trigger");
	if (body.signingSecretCredentialReferenceId) {
		const credentialRef = await getCredentialReference(db)({
			scopes: {
				tenantId,
				projectId
			},
			id: body.signingSecretCredentialReferenceId
		});
		if (!credentialRef) throw createApiError({
			code: "bad_request",
			message: `Credential reference not found: ${body.signingSecretCredentialReferenceId}`
		});
		if (credentialRef.userId) throw createApiError({
			code: "bad_request",
			message: "Only project-scoped credentials can be attached to triggers. User-scoped credentials are not allowed."
		});
	}
	let hashedAuthentication;
	const authInput = body.authentication;
	if (authInput?.headers && authInput.headers.length > 0) hashedAuthentication = { headers: await hashAuthenticationHeaders(authInput.headers) };
	const trigger = await createTrigger(db)({
		id,
		tenantId,
		projectId,
		agentId,
		name: body.name,
		description: body.description,
		enabled: body.enabled !== void 0 ? body.enabled : true,
		inputSchema: body.inputSchema,
		outputTransform: body.outputTransform,
		messageTemplate: body.messageTemplate,
		authentication: hashedAuthentication,
		signingSecretCredentialReferenceId: body.signingSecretCredentialReferenceId,
		signatureVerification: body.signatureVerification
	});
	const { tenantId: _tid, projectId: _pid, agentId: _aid, ...triggerWithoutScopes } = trigger;
	return c.json({ data: {
		...triggerWithoutScopes,
		webhookUrl: generateWebhookUrl({
			baseUrl: apiBaseUrl,
			tenantId,
			projectId,
			agentId,
			triggerId: trigger.id
		})
	} }, 201);
});
/**
* Update Trigger
*/
app.openapi(createRoute({
	method: "patch",
	path: "/{id}",
	summary: "Update Trigger",
	operationId: "update-trigger",
	tags: ["Triggers"],
	request: {
		params: TenantProjectAgentIdParamsSchema,
		body: { content: { "application/json": { schema: TriggerApiUpdateSchema } } }
	},
	responses: {
		200: {
			description: "Trigger updated successfully",
			content: { "application/json": { schema: TriggerWithWebhookUrlResponse } }
		},
		...commonGetErrorResponses
	}
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, agentId, id } = c.req.valid("param");
	const body = c.req.valid("json");
	const apiBaseUrl = env.INKEEP_AGENTS_API_URL;
	if (!(body.name !== void 0 || body.description !== void 0 || body.enabled !== void 0 || body.inputSchema !== void 0 || body.outputTransform !== void 0 || body.messageTemplate !== void 0 || body.authentication !== void 0 || body.signingSecretCredentialReferenceId !== void 0 || body.signatureVerification !== void 0)) throw createApiError({
		code: "bad_request",
		message: "No fields to update"
	});
	logger.debug({
		tenantId,
		projectId,
		agentId,
		triggerId: id
	}, "Updating trigger");
	if (body.signingSecretCredentialReferenceId) {
		const credentialRef = await getCredentialReference(db)({
			scopes: {
				tenantId,
				projectId
			},
			id: body.signingSecretCredentialReferenceId
		});
		if (!credentialRef) throw createApiError({
			code: "bad_request",
			message: `Credential reference not found: ${body.signingSecretCredentialReferenceId}`
		});
		if (credentialRef.userId) throw createApiError({
			code: "bad_request",
			message: "Only project-scoped credentials can be attached to triggers. User-scoped credentials are not allowed."
		});
	}
	let hashedAuthentication;
	const authInput = body.authentication;
	if (authInput?.headers && authInput.headers.length > 0) {
		const existingAuth = (await getTriggerById(db)({
			scopes: {
				tenantId,
				projectId,
				agentId
			},
			triggerId: id
		}))?.authentication;
		const hashedHeaders = [];
		for (const header of authInput.headers) if (header.keepExisting) {
			const existingHeader = existingAuth?.headers?.find((h) => h.name === header.name);
			if (existingHeader) hashedHeaders.push({
				name: header.name,
				valueHash: existingHeader.valueHash,
				valuePrefix: existingHeader.valuePrefix
			});
		} else if (header.value) {
			const hashed = await hashAuthenticationHeaders([{
				name: header.name,
				value: header.value
			}]);
			hashedHeaders.push(hashed[0]);
		}
		hashedAuthentication = hashedHeaders.length > 0 ? { headers: hashedHeaders } : void 0;
	} else if (body.authentication !== void 0) hashedAuthentication = body.authentication;
	const updatedTrigger = await updateTrigger(db)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		triggerId: id,
		data: {
			name: body.name,
			description: body.description,
			enabled: body.enabled,
			inputSchema: body.inputSchema,
			outputTransform: body.outputTransform,
			messageTemplate: body.messageTemplate,
			authentication: hashedAuthentication,
			signingSecretCredentialReferenceId: body.signingSecretCredentialReferenceId,
			signatureVerification: body.signatureVerification
		}
	});
	if (!updatedTrigger) throw createApiError({
		code: "not_found",
		message: "Trigger not found"
	});
	const { tenantId: _tid, projectId: _pid, agentId: _aid, ...triggerWithoutScopes } = updatedTrigger;
	return c.json({ data: {
		...triggerWithoutScopes,
		webhookUrl: generateWebhookUrl({
			baseUrl: apiBaseUrl,
			tenantId,
			projectId,
			agentId,
			triggerId: updatedTrigger.id
		})
	} });
});
/**
* Delete Trigger
*/
app.openapi(createRoute({
	method: "delete",
	path: "/{id}",
	summary: "Delete Trigger",
	operationId: "delete-trigger",
	tags: ["Triggers"],
	request: { params: TenantProjectAgentIdParamsSchema },
	responses: {
		204: { description: "Trigger deleted successfully" },
		...commonGetErrorResponses
	}
}), async (c) => {
	const db = c.get("db");
	const { tenantId, projectId, agentId, id } = c.req.valid("param");
	logger.debug({
		tenantId,
		projectId,
		agentId,
		triggerId: id
	}, "Deleting trigger");
	if (!await getTriggerById(db)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		triggerId: id
	})) throw createApiError({
		code: "not_found",
		message: "Trigger not found"
	});
	await deleteTrigger(db)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		triggerId: id
	});
	return c.body(null, 204);
});
/**
* ========================================
* Trigger Invocation Endpoints
* ========================================
*/
const TriggerInvocationQueryParamsSchema = PaginationQueryParamsSchema.extend({
	status: TriggerInvocationStatusEnum.optional().openapi({ description: "Filter by invocation status" }),
	from: z.string().datetime().optional().openapi({ description: "Start date for filtering (ISO8601)" }),
	to: z.string().datetime().optional().openapi({ description: "End date for filtering (ISO8601)" })
}).openapi("TriggerInvocationQueryParams");
/**
* List Trigger Invocations
*/
app.openapi(createRoute({
	method: "get",
	path: "/{id}/invocations",
	summary: "List Trigger Invocations",
	operationId: "list-trigger-invocations",
	tags: ["Triggers"],
	request: {
		params: TenantProjectAgentIdParamsSchema,
		query: TriggerInvocationQueryParamsSchema
	},
	responses: {
		200: {
			description: "List of trigger invocations retrieved successfully",
			content: { "application/json": { schema: TriggerInvocationListResponse } }
		},
		...commonGetErrorResponses
	},
	...speakeasyOffsetLimitPagination
}), async (c) => {
	const { tenantId, projectId, agentId, id: triggerId } = c.req.valid("param");
	const { page, limit, status, from, to } = c.req.valid("query");
	logger.debug({
		tenantId,
		projectId,
		agentId,
		triggerId,
		status,
		from,
		to
	}, "Listing trigger invocations");
	const result = await listTriggerInvocationsPaginated(runDbClient_default)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		triggerId,
		pagination: {
			page,
			limit
		},
		filters: {
			status,
			from,
			to
		}
	});
	const dataWithoutScopes = result.data.map((invocation) => {
		const { tenantId: _tid, projectId: _pid, agentId: _aid, ...rest } = invocation;
		return rest;
	});
	return c.json({
		data: dataWithoutScopes,
		pagination: result.pagination
	});
});
/**
* Get Trigger Invocation by ID
*/
app.openapi(createRoute({
	method: "get",
	path: "/{id}/invocations/{invocationId}",
	summary: "Get Trigger Invocation",
	operationId: "get-trigger-invocation-by-id",
	tags: ["Triggers"],
	request: { params: TenantProjectAgentIdParamsSchema.extend({ invocationId: z.string().describe("Trigger Invocation ID") }) },
	responses: {
		200: {
			description: "Trigger invocation found",
			content: { "application/json": { schema: TriggerInvocationResponse } }
		},
		...commonGetErrorResponses
	}
}), async (c) => {
	const { tenantId, projectId, agentId, id: triggerId, invocationId } = c.req.valid("param");
	logger.debug({
		tenantId,
		projectId,
		agentId,
		triggerId,
		invocationId
	}, "Getting trigger invocation");
	const invocation = await getTriggerInvocationById(runDbClient_default)({
		scopes: {
			tenantId,
			projectId,
			agentId
		},
		triggerId,
		invocationId
	});
	if (!invocation) throw createApiError({
		code: "not_found",
		message: "Trigger invocation not found"
	});
	const { tenantId: _tid, projectId: _pid, agentId: _aid, ...invocationWithoutScopes } = invocation;
	return c.json({ data: invocationWithoutScopes });
});
var triggers_default = app;

//#endregion
export { triggers_default as default };