/**
 * Trace Collector — SF_TRACE_ENABLED gating
 *
 * Thin wrapper around the trace primitives that respects SF_TRACE_ENABLED.
 * When disabled (default), all functions are no-ops with zero overhead.
 * When enabled, creates and manages the active trace instance.
 */
import {
	addChildSpan,
	addError,
	addEvent,
	createSpan,
	createTrace,
	endSpan,
	exportTraceToProject,
	finalizeTrace,
	findSpan,
} from "../../traces.js";
// ---------------------------------------------------------------------------
// Environment flag
// ---------------------------------------------------------------------------
/** Returns true when structured trace collection is enabled. */
export function isTraceEnabled() {
	return process.env.SF_TRACE_ENABLED === "1";
}
// ---------------------------------------------------------------------------
// Collector state
// ---------------------------------------------------------------------------
let _activeTrace = null;
// ---------------------------------------------------------------------------
// Lifecycle
// ---------------------------------------------------------------------------
/**
 * Initialize a new trace when SF_TRACE_ENABLED=1.
 * Returns null when disabled — callers should early-return to skip all trace work.
 */
export function initTraceCollector(projectRoot, sessionId, command, model) {
	if (!isTraceEnabled()) return null;
	const trace = createTrace(projectRoot, sessionId, command, model);
	_activeTrace = trace;
	return trace;
}
/** Finalize and flush the active trace to disk. Idempotent. */
export function flushTrace(projectRoot) {
	if (!_activeTrace) return;
	finalizeTrace(_activeTrace);
	exportTraceToProject(_activeTrace, projectRoot);
	_activeTrace = null;
}
/** Get the active trace, or null if not initialized or disabled. */
export function getActiveTrace() {
	return _activeTrace;
}
// ---------------------------------------------------------------------------
// Span operations (passthrough to trace primitives)
// ---------------------------------------------------------------------------
/** Create and attach a unit span to the active trace root. */
export function startUnitSpan(unitType, unitId, attributes = {}) {
	const trace = _activeTrace;
	if (!trace) return null;
	const span = createSpan(`${unitType}:${unitId}`, "unit", {
		unitType,
		unitId,
		...attributes,
	});
	addChildSpan(trace.rootSpan, span);
	return span;
}
/** Create and attach a tool span as a child of the given unit span. */
export function startToolSpan(
	parentSpan,
	toolName,
	toolCallId,
	attributes = {},
) {
	const span = createSpan(`tool:${toolName}`, "tool", {
		toolName,
		toolCallId,
		...attributes,
	});
	addChildSpan(parentSpan, span);
	return span;
}
/** Mark a span as complete. */
export function completeSpan(span, status = "ok") {
	endSpan(span, status);
}
/** Record a named event on a span. */
export function traceEvent(span, name, attrs) {
	addEvent(span, name, attrs);
}
/** Record an error on a span. */
export function traceError(span, message, stack) {
	addError(span, message, stack);
}
/** Find a span in the active trace by ID. */
export function findTraceSpan(id) {
	if (!_activeTrace) return undefined;
	return findSpan(_activeTrace.rootSpan, id);
}
// ---------------------------------------------------------------------------
// Cost aggregation helpers
// ---------------------------------------------------------------------------
/** Update cost/token attributes on the root span. */
export function setTraceCost(
	inputTokens,
	outputTokens,
	cacheReadTokens,
	cacheWriteTokens,
	costUsd,
) {
	if (!_activeTrace) return;
	_activeTrace.rootSpan.attributes = {
		..._activeTrace.rootSpan.attributes,
		inputTokens,
		outputTokens,
		cacheReadTokens,
		cacheWriteTokens,
		costUsd,
	};
}
/** Set the exit code on the root span. */
export function setTraceExitCode(code) {
	if (!_activeTrace) return;
	_activeTrace.rootSpan.attributes.exitCode = code;
}
