"use strict";
/**
 * Interceptor lifecycle helpers.
 *
 * Extracted from the main execute() function so the interceptor
 * reads as a high-level pipeline. Each helper handles one phase
 * of the workflow lifecycle.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractWorkflowIdentity = extractWorkflowIdentity;
exports.deriveTaskQueue = deriveTaskQueue;
exports.resolveReRun = resolveReRun;
exports.ensureTaskWithRouting = ensureTaskWithRouting;
exports.publishStartedEvents = publishStartedEvents;
exports.completePlainResult = completePlainResult;
const publish_1 = require("../../lib/events/publish");
// ── Helpers ──────────────────────────────────────────────────────────────────
/** Extract workflow identity fields from the HotMesh context map. */
function extractWorkflowIdentity(ctx) {
    return {
        workflowId: ctx.get('workflowId'),
        workflowName: ctx.get('workflowName'),
        workflowTopic: ctx.get('workflowTopic'),
        workflowTrace: ctx.get('workflowTrace'),
        workflowSpan: ctx.get('workflowSpan'),
    };
}
/** Derive the task queue from the workflow topic. */
function deriveTaskQueue(wf) {
    return wf.workflowTopic
        ? wf.workflowTopic.replace(new RegExp(`-${wf.workflowName}$`), '')
        : 'long-tail-examples';
}
/**
 * Detect re-runs and resolve the prior escalation.
 *
 * A re-run occurs when `envelope.resolver` + `envelope.lt.escalationId`
 * are both present — meaning a human (or AI) resolved an escalation
 * and a new workflow was started with the resolver data.
 */
async function resolveReRun(activities, envelope, existingTask, wf, taskQueue) {
    const isReRun = !!(envelope?.resolver && envelope?.lt?.escalationId);
    let task = existingTask;
    let metadata = existingTask?.metadata;
    // If re-run but no task found by workflowId, look up by the original taskId
    if (isReRun && !task && envelope?.lt?.taskId) {
        task = await activities.ltGetTask(envelope.lt.taskId);
        metadata = task?.metadata;
    }
    // Resolve the old escalation (skip auto-triage synthetic IDs —
    // the triage orchestrator already resolved those)
    const escalationId = envelope?.lt?.escalationId;
    const isRealEscalation = isReRun && escalationId && !escalationId.startsWith('auto-triage-');
    if (isRealEscalation) {
        await activities.ltResolveEscalation({
            escalationId: escalationId,
            resolverPayload: envelope.resolver,
        });
        (0, publish_1.publishEscalationEvent)({
            type: 'escalation.resolved',
            source: 'interceptor',
            workflowId: wf.workflowId,
            workflowName: wf.workflowName,
            taskQueue,
            taskId: task?.id || existingTask?.id,
            escalationId: escalationId,
            originId: envelope?.lt?.originId,
            status: 'resolved',
        });
    }
    return { isReRun, task, metadata };
}
/**
 * Ensure a task record exists and resolve routing + origin lineage.
 *
 * Handles three cases:
 * - Task already exists (from executeLT pre-creation) → use it
 * - Re-run task found by escalation context → reuse it
 * - No task → create a standalone task
 *
 * Also injects originId back into the envelope for downstream consistency.
 */
async function ensureTaskWithRouting(activities, wf, envelope, existingTask, taskQueue, reRun) {
    let taskId = reRun.task?.id || existingTask?.id;
    let routing = reRun.metadata || existingTask?.metadata;
    // Fallback: envelope carries routing fields (e.g., from triage auto-resolve)
    // but the task metadata doesn't have them
    if (!routing?.parentWorkflowId && envelope?.lt?.parentWorkflowId) {
        routing = {
            ...(routing || {}),
            signalId: envelope.lt.signalId,
            parentWorkflowId: envelope.lt.parentWorkflowId,
            parentTaskQueue: envelope.lt.parentTaskQueue,
            parentWorkflowType: envelope.lt.parentWorkflowType,
        };
    }
    // Canonical originId: traces back to the root workflow
    const originId = envelope?.lt?.originId
        || reRun.task?.origin_id
        || existingTask?.origin_id
        || wf.workflowId;
    // Inject originId so escalation records, stored envelopes, and events
    // all read it consistently
    if (envelope) {
        envelope.lt = { ...envelope.lt, originId };
    }
    // Create task if none exists, or start a pending one
    if (!taskId) {
        taskId = await activities.ltCreateTask({
            workflowId: wf.workflowId,
            workflowType: wf.workflowName,
            ltType: wf.workflowName,
            taskQueue,
            signalId: `lt-standalone-${wf.workflowId}`,
            parentWorkflowId: wf.workflowId,
            originId,
            parentId: envelope?.lt?.parentId,
            envelope: JSON.stringify(envelope || {}),
            traceId: wf.workflowTrace,
            spanId: wf.workflowSpan,
            initiatedBy: envelope?.lt?.initiatedBy ?? envelope?.lt?.userId,
            executingAs: envelope?.lt?.initiatedBy ? envelope?.lt?.userId : undefined,
            status: 'in_progress',
        });
    }
    else if (existingTask?.status === 'pending') {
        await activities.ltStartTask(taskId);
    }
    return { taskId, routing, originId };
}
/** Publish workflow.started + task.started events. */
function publishStartedEvents(wf, taskQueue, taskId, originId) {
    (0, publish_1.publishWorkflowEvent)({
        type: 'workflow.started',
        source: 'interceptor',
        workflowId: wf.workflowId,
        workflowName: wf.workflowName,
        taskQueue,
        taskId,
        originId,
        status: 'running',
    });
    (0, publish_1.publishTaskEvent)({
        type: 'task.started',
        source: 'interceptor',
        workflowId: wf.workflowId,
        workflowName: wf.workflowName,
        taskQueue,
        taskId: taskId,
        originId,
        status: 'in_progress',
    });
}
/** Complete a task and signal parent for plain (non-LTReturn) results. */
async function completePlainResult(activities, wf, taskQueue, taskId, routing, result) {
    if (taskId) {
        await activities.ltCompleteTask({
            taskId,
            data: JSON.stringify(result),
            workflowId: wf.workflowId,
            workflowName: wf.workflowName,
            taskQueue,
        });
    }
    if (routing?.parentWorkflowId && routing?.signalId) {
        await activities.ltSignalParent({
            parentTaskQueue: routing.parentTaskQueue,
            parentWorkflowType: routing.parentWorkflowType,
            parentWorkflowId: routing.parentWorkflowId,
            signalId: routing.signalId,
            data: result,
        });
    }
}
