import runDbClient_default from "../../../data/db/runDbClient.js";
import { getLogger as getLogger$1 } from "../../../logger.js";
import { scheduledTriggerRunnerWorkflow } from "../workflow/functions/scheduledTriggerRunner.js";
import { advanceScheduledTriggerNextRunAt, computeNextRunAt, findDueScheduledTriggersAcrossProjects, getScheduledTriggerUsers } from "@inkeep/agents-core";
import { start } from "workflow/api";

//#region src/domains/run/services/triggerDispatcher.ts
const logger = getLogger$1("triggerDispatcher");
async function dispatchDueTriggers() {
	const now = /* @__PURE__ */ new Date();
	const dueTriggers = await findDueScheduledTriggersAcrossProjects(runDbClient_default)({ asOf: now.toISOString() });
	if (dueTriggers.length === 0) return { dispatched: 0 };
	logger.info({ dueCount: dueTriggers.length }, "Found due triggers");
	let totalDispatched = 0;
	const results = await Promise.allSettled(dueTriggers.map((trigger) => dispatchSingleTrigger(trigger)));
	for (let i = 0; i < results.length; i++) {
		const result = results[i];
		if (result.status === "fulfilled") totalDispatched += result.value;
		else {
			const trigger = dueTriggers[i];
			logger.error({
				error: result.reason,
				scheduledTriggerId: trigger.id,
				tenantId: trigger.tenantId,
				projectId: trigger.projectId,
				agentId: trigger.agentId
			}, "Dispatch failed unexpectedly");
		}
	}
	return { dispatched: totalDispatched };
}
async function dispatchSingleTrigger(trigger) {
	const { tenantId, projectId, agentId, id: scheduledTriggerId } = trigger;
	const nextRunAt = !trigger.cronExpression ? null : computeNextRunAt({
		cronExpression: trigger.cronExpression,
		cronTimezone: trigger.cronTimezone,
		runAt: trigger.runAt,
		lastScheduledFor: trigger.nextRunAt
	});
	const scheduledFor = trigger.nextRunAt ?? (/* @__PURE__ */ new Date()).toISOString();
	const dispatchDelayMs = trigger.dispatchDelayMs ?? 0;
	const joinTableUsers = await getScheduledTriggerUsers(runDbClient_default)({
		tenantId,
		scheduledTriggerId
	});
	let workflowsStarted = 0;
	if (joinTableUsers.length > 0) {
		const payloads = joinTableUsers.map((row, index) => ({
			tenantId,
			projectId,
			agentId,
			scheduledTriggerId,
			scheduledFor,
			ref: trigger.ref,
			runAsUserId: row.userId,
			delayBeforeExecutionMs: index * dispatchDelayMs
		}));
		const workflowResults = await Promise.allSettled(payloads.map((payload) => start(scheduledTriggerRunnerWorkflow, [payload])));
		for (let i = 0; i < workflowResults.length; i++) if (workflowResults[i].status === "fulfilled") workflowsStarted++;
		else {
			const error = workflowResults[i].reason;
			logger.error({
				scheduledTriggerId,
				userId: joinTableUsers[i].userId,
				error
			}, "Failed to start workflow for user");
		}
	} else {
		await start(scheduledTriggerRunnerWorkflow, [{
			tenantId,
			projectId,
			agentId,
			scheduledTriggerId,
			scheduledFor,
			ref: trigger.ref
		}]);
		workflowsStarted = 1;
	}
	if (workflowsStarted > 0) try {
		await advanceScheduledTriggerNextRunAt(runDbClient_default)({
			scopes: {
				tenantId,
				projectId,
				agentId
			},
			scheduledTriggerId,
			nextRunAt
		});
	} catch (err) {
		logger.error({
			scheduledTriggerId,
			err
		}, "Failed to advance next_run_at after workflow start; next tick will retry (idempotent)");
	}
	else logger.warn({
		scheduledTriggerId,
		scheduledFor
	}, "No workflows started for trigger tick; not advancing nextRunAt so next tick retries");
	logger.info({
		scheduledTriggerId,
		scheduledFor,
		workflowsStarted
	}, "Trigger dispatched");
	return workflowsStarted;
}

//#endregion
export { dispatchDueTriggers };