import { WorkflowInstance } from "../data/entities.js";
import { logWorkflowEvent } from "./event-logger.js";
import {
  executeSendEmail,
  executeEmitEvent,
  executeUpdateEntity,
  executeCallWebhook,
  executeFunction
} from "./activity-executor.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("workflows").child({ component: "activity-worker" });
function createActivityWorkerHandler(em, container) {
  return async (job, ctx) => {
    const { payload } = job;
    const startTime = Date.now();
    if (payload.kind === "timer") {
      logger.debug("Firing timer for instance", { instanceId: payload.workflowInstanceId, jobId: ctx.jobId });
      try {
        const { fireTimer } = await import("./timer-handler.js");
        await fireTimer(em, container, {
          instanceId: payload.workflowInstanceId,
          stepInstanceId: payload.stepInstanceId,
          tenantId: payload.tenantId,
          organizationId: payload.organizationId,
          userId: payload.userId
        });
      } catch (error) {
        logger.error("Failed to fire timer for instance", { instanceId: payload.workflowInstanceId, err: error });
        throw error;
      }
      return;
    }
    logger.debug("Processing activity", { activityId: payload.activityId, jobId: ctx.jobId });
    try {
      const instance = await em.findOne(WorkflowInstance, {
        id: payload.workflowInstanceId,
        tenantId: payload.tenantId,
        organizationId: payload.organizationId
      });
      if (!instance) {
        throw new Error(`Workflow instance ${payload.workflowInstanceId} not found`);
      }
      const activityContext = {
        workflowInstance: instance,
        workflowContext: payload.workflowContext,
        stepContext: payload.stepContext,
        stepInstanceId: payload.stepInstanceId,
        userId: payload.userId
      };
      let result;
      const executeActivityByType = async () => {
        switch (payload.activityType) {
          case "SEND_EMAIL":
            return await executeSendEmail(payload.activityConfig, activityContext, container);
          case "EMIT_EVENT":
            return await executeEmitEvent(payload.activityConfig, activityContext, container);
          case "UPDATE_ENTITY":
            return await executeUpdateEntity(
              em,
              payload.activityConfig,
              activityContext,
              container
            );
          case "CALL_WEBHOOK":
            return await executeCallWebhook(payload.activityConfig, activityContext);
          case "EXECUTE_FUNCTION":
            return await executeFunction(payload.activityConfig, activityContext, container);
          case "WAIT":
            return { waited: true, async: true };
          default:
            throw new Error(`Unsupported activity type: ${payload.activityType}`);
        }
      };
      if (payload.timeoutMs) {
        result = await Promise.race([
          executeActivityByType(),
          new Promise(
            (_, reject) => setTimeout(
              () => reject(new Error(`Activity timeout after ${payload.timeoutMs}ms`)),
              payload.timeoutMs
            )
          )
        ]);
      } else {
        result = await executeActivityByType();
      }
      const executionTimeMs = Date.now() - startTime;
      await logWorkflowEvent(em, {
        workflowInstanceId: payload.workflowInstanceId,
        stepInstanceId: payload.stepInstanceId,
        eventType: "ACTIVITY_COMPLETED",
        eventData: {
          activityId: payload.activityId,
          activityName: payload.activityName,
          async: true,
          jobId: ctx.jobId,
          attemptNumber: ctx.attemptNumber,
          executionTimeMs,
          output: result
        },
        userId: payload.userId,
        tenantId: payload.tenantId,
        organizationId: payload.organizationId
      });
      logger.debug("Activity completed", { activityId: payload.activityId, executionTimeMs });
      await checkAndResumeWorkflow(em, container, payload.workflowInstanceId);
    } catch (error) {
      const executionTimeMs = Date.now() - startTime;
      logger.error("Activity failed", { activityId: payload.activityId, err: error });
      await logWorkflowEvent(em, {
        workflowInstanceId: payload.workflowInstanceId,
        stepInstanceId: payload.stepInstanceId,
        eventType: "ACTIVITY_FAILED",
        eventData: {
          activityId: payload.activityId,
          activityName: payload.activityName,
          async: true,
          jobId: ctx.jobId,
          attemptNumber: ctx.attemptNumber,
          error: error.message,
          executionTimeMs
        },
        userId: payload.userId,
        tenantId: payload.tenantId,
        organizationId: payload.organizationId
      });
      if (ctx.attemptNumber >= (payload.retryPolicy?.maxAttempts || 1)) {
        await checkAndResumeWorkflow(em, container, payload.workflowInstanceId);
      }
      throw error;
    }
  };
}
async function checkAndResumeWorkflow(em, container, workflowInstanceId) {
  const { resumeWorkflowAfterActivities } = await import("./workflow-executor.js");
  try {
    await resumeWorkflowAfterActivities(em, container, workflowInstanceId);
  } catch (error) {
    if (!error.message?.includes("Activities still pending")) {
      logger.error("Failed to resume workflow", { instanceId: workflowInstanceId, err: error });
    }
  }
}
export {
  createActivityWorkerHandler
};
//# sourceMappingURL=activity-worker-handler.js.map
