// Implementation for createWorkflowContext, createNodeContext
import { v4 as uuidv4 } from 'uuid';
import { IWorkflowContext, INodeContext, NodeStatus } from '../types/runtime';

export function createWorkflowContext(
    definitionId: string,
    definitionName: string | undefined,
    input: Record<string, any>,
    extras: Partial<IWorkflowContext> = {}
): IWorkflowContext {
    return {
        workflowId: uuidv4(), // Generate unique instance ID
        definitionId,
        definitionName,
        input: Object.freeze({ ...input }), // Immutable input
        status: NodeStatus.PENDING,
        variables: {}, // Mutable state
        startTime: new Date(),
        history: [], // Mutable history log
        logs: [],    // Mutable simple logs
        // Spread extras like tenantId, userId etc.
        ...extras,
    };
}

export function createNodeContext(
    workflowContext: IWorkflowContext,
    stepId: string,
    nodeId: string,
    retryAttempt: number // Pass retry attempt
): INodeContext {
    // Provide helper functions bound to the workflow context
    const getVariable = <T = any>(name: string): T | undefined => workflowContext.variables[name];
    const setVariable = (name: string, value: any): void => { workflowContext.variables[name] = value; };
    const log = (message: string): void => {
        const logEntry = { timestamp: new Date(), message };
        // Add to both node-specific and workflow logs?
        (nodeContext as any).logs.push(logEntry); // Need temp 'any' due to initialization order
        workflowContext.logs.push(`[${stepId}|${nodeId}] ${message}`);
    };

    const nodeContext: INodeContext = {
        workflowContext,
        stepId,
        nodeId,
        input: {}, // This will be populated by executor using inputMapping
        status: NodeStatus.PENDING,
        output: undefined,
        startTime: new Date(),
        retries: retryAttempt,
        logs: [],
        // Add helper methods
        getVariable,
        setVariable,
        log,
    };
    return nodeContext;
}