// src/flow/FlowContext.ts

export interface IFlowContextData {
  traceId: string;
  flowId: string;
  userId?: string;
  attributes?: Record<string, unknown>;
}

/**
 * Immutable context for an ad-hoc flow / query.
 * It is orthogonal to the bus; you can embed it in payloads if you want
 * propagation, but nothing in the kernel depends on it.
 */
export class FlowContext {
  readonly traceId: string;
  readonly flowId: string;

  readonly userId?: string;
  readonly attributes: Record<string, unknown>;

  constructor(data: IFlowContextData) {
    this.traceId = data.traceId;
    this.flowId = data.flowId;

    this.userId = data.userId;
    this.attributes = { ...(data.attributes ?? {}) };
  }

  withAttributes(extra: Record<string, unknown>): FlowContext {
    return new FlowContext({
      traceId: this.traceId,
      flowId: this.flowId,
      userId: this.userId,
      attributes: { ...this.attributes, ...extra },
    });
  }
}

/**
 * Helper to create a new FlowContext, generating IDs when needed.
 */
export function createFlowContext(
  seed?: Partial<IFlowContextData>
): FlowContext {
  const now = Date.now();
  const entropy = Math.random().toString(36).slice(2);
  const baseId = `${now.toString(36)}-${entropy}`;

  const traceId = seed?.traceId ?? baseId;
  const flowId = seed?.flowId ?? traceId;

  return new FlowContext({
    traceId,
    flowId,
    userId: seed?.userId,
    attributes: seed?.attributes,
  });
}
