import { ExecutionPhase, WorkflowTaskStatus, } from "@stigmer/protos/ai/stigmer/agentic/workflowexecution/v1/enum_pb";
const BIGINT_ZERO = BigInt(0);
const TERMINAL_TASK_STATUSES = new Set([
    WorkflowTaskStatus.WORKFLOW_TASK_COMPLETED,
    WorkflowTaskStatus.WORKFLOW_TASK_FAILED,
    WorkflowTaskStatus.WORKFLOW_TASK_SKIPPED,
]);
function parseIsoDate(iso) {
    if (!iso)
        return null;
    const d = new Date(iso);
    return Number.isNaN(d.getTime()) ? null : d;
}
function extractRetryCount(metadata) {
    if (!metadata?.fields)
        return 0;
    const retryField = metadata.fields["retry_count"] ?? metadata.fields["retryCount"];
    if (retryField && typeof retryField === "object" && retryField !== null && "numberValue" in retryField) {
        return Math.max(0, Math.floor(retryField.numberValue ?? 0));
    }
    return 0;
}
/**
 * Derives a UI-ready {@link ExecutionRow} from a raw {@link WorkflowExecution}.
 *
 * Pure function with zero side effects. Computes duration, identifies
 * the failed/current task, counts retries, and normalizes bigint fields.
 */
export function deriveExecutionRow(exec) {
    const meta = exec.metadata;
    const status = exec.status;
    const tasks = status?.tasks ?? [];
    const startedAt = parseIsoDate(status?.startedAt);
    const completedAt = parseIsoDate(status?.completedAt);
    let durationMs = null;
    if (startedAt && completedAt) {
        durationMs = completedAt.getTime() - startedAt.getTime();
    }
    else if (startedAt && status?.phase === ExecutionPhase.EXECUTION_IN_PROGRESS) {
        durationMs = Date.now() - startedAt.getTime();
    }
    let failedTaskName = null;
    let currentTaskName = null;
    let completedTaskCount = 0;
    let retryCount = 0;
    let hasHumanWait = false;
    for (const task of tasks) {
        if (TERMINAL_TASK_STATUSES.has(task.status)) {
            completedTaskCount++;
        }
        if (!failedTaskName && task.status === WorkflowTaskStatus.WORKFLOW_TASK_FAILED) {
            failedTaskName = task.taskName || null;
        }
        if (!currentTaskName && task.status === WorkflowTaskStatus.WORKFLOW_TASK_IN_PROGRESS) {
            currentTaskName = task.taskName || null;
        }
        if (task.status === WorkflowTaskStatus.WORKFLOW_TASK_WAITING_APPROVAL) {
            hasHumanWait = true;
            if (!currentTaskName)
                currentTaskName = task.taskName || null;
        }
        retryCount += extractRetryCount(task.metadata);
    }
    const costMicros = BigInt(status?.totalCostMicros ?? 0);
    const inputTokens = BigInt(status?.totalInputTokens ?? 0);
    const outputTokens = BigInt(status?.totalOutputTokens ?? 0);
    return {
        id: meta?.id ?? "",
        name: meta?.name || meta?.slug || "",
        phase: status?.phase ?? ExecutionPhase.EXECUTION_PHASE_UNSPECIFIED,
        startedAt,
        completedAt,
        durationMs,
        costMicros,
        inputTokens,
        outputTokens,
        totalTokens: inputTokens + outputTokens,
        taskCount: tasks.length,
        completedTaskCount,
        failedTaskName,
        currentTaskName,
        retryCount,
        hasHumanWait,
        error: status?.error || null,
        _source: exec,
    };
}
/**
 * Batch-derives execution rows from a list of raw executions.
 * Preserves input order.
 */
export function deriveExecutionRows(executions) {
    return executions.map(deriveExecutionRow);
}
const SORT_COMPARATORS = {
    name: (a, b) => a.name.localeCompare(b.name),
    phase: (a, b) => a.phase - b.phase,
    startedAt: (a, b) => (a.startedAt?.getTime() ?? 0) - (b.startedAt?.getTime() ?? 0),
    duration: (a, b) => (a.durationMs ?? -1) - (b.durationMs ?? -1),
    cost: (a, b) => Number(a.costMicros - b.costMicros),
    tokens: (a, b) => Number(a.totalTokens - b.totalTokens),
    tasks: (a, b) => a.taskCount - b.taskCount,
};
/**
 * Sorts execution rows by a given field and direction.
 * Returns a new array (does not mutate the input).
 */
export function sortExecutionRows(rows, field, direction) {
    const cmp = SORT_COMPARATORS[field];
    const multiplier = direction === "desc" ? -1 : 1;
    return [...rows].sort((a, b) => multiplier * cmp(a, b));
}
/**
 * Applies client-side filters to execution rows.
 * Returns a new array containing only rows that match all criteria.
 */
export function filterExecutionRows(rows, filters) {
    return rows.filter((row) => {
        if (filters.phases?.length && !filters.phases.includes(row.phase)) {
            return false;
        }
        if (filters.minDurationMs != null && (row.durationMs ?? -1) < filters.minDurationMs) {
            return false;
        }
        if (filters.maxDurationMs != null && (row.durationMs ?? Infinity) > filters.maxDurationMs) {
            return false;
        }
        if (filters.minCostMicros != null && row.costMicros < filters.minCostMicros) {
            return false;
        }
        if (filters.maxCostMicros != null && row.costMicros > filters.maxCostMicros) {
            return false;
        }
        if (filters.failedTaskName && row.failedTaskName !== filters.failedTaskName) {
            return false;
        }
        if (filters.hasRetries && row.retryCount === 0) {
            return false;
        }
        return true;
    });
}
//# sourceMappingURL=derive-execution-row.js.map