/**
 * OTel session tracing — stub.
 *
 * The upstream module emitted nested OpenTelemetry spans for the LLM
 * request → tool execution lifecycle, with hooks/blocks broken out so the
 * trace UI could render a Gantt of agent turns. Sandcode has no first-party
 * tracing backend wired up; this stub satisfies the call-site signatures
 * (services/api/messages, services/api/logging, services/tools/toolExecution,
 * utils/hooks, utils/processUserInput/processTextPrompt) without instrumenting
 * anything.
 *
 * All start* functions return a no-op {@link Span}. End/add functions
 * accept a Span and ignore it. {@link isBetaTracingEnabled} returns false
 * so callers' "if tracing on" branches stay cold.
 */

/** Minimal OTel-Span-shaped object — enough for callers' end-call ergonomics. */
export type Span = {
  end: () => void
  setAttribute: (_key: string, _value: unknown) => void
  setAttributes: (_attrs: Record<string, unknown>) => void
  recordException: (_e: unknown) => void
  addEvent: (_name: string, _attrs?: Record<string, unknown>) => void
}

const NOOP_SPAN: Span = {
  end: () => {},
  setAttribute: () => {},
  setAttributes: () => {},
  recordException: () => {},
  addEvent: () => {},
}

/** Caller-friendly context for an LLM request span. */
export type LLMRequestNewContext = {
  model?: string
  requestId?: string
  invokingRequestId?: string
  // Wide-open: callers stash arbitrary fields on this. The real shape would
  // be tighter, but for the stub anything-goes is fine.
  [k: string]: unknown
}

/** Build-time gate — callers branch on this to skip span work entirely. */
export function isBetaTracingEnabled(): boolean {
  return false
}

// ─── LLM request lifecycle ─────────────────────────────────────────────────

export function startLLMRequestSpan(_ctx?: LLMRequestNewContext): Span {
  return NOOP_SPAN
}

export function endLLMRequestSpan(_span?: Span, _result?: unknown): void {
  /* no-op */
}

// ─── Tool execution lifecycle ──────────────────────────────────────────────

export function startToolSpan(_toolName?: string, _attrs?: Record<string, unknown>): Span {
  return NOOP_SPAN
}

export function endToolSpan(_span?: Span, _result?: unknown): void {
  /* no-op */
}

export function startToolExecutionSpan(_toolName?: string, _attrs?: Record<string, unknown>): Span {
  return NOOP_SPAN
}

export function endToolExecutionSpan(_span?: Span, _result?: unknown): void {
  /* no-op */
}

export function startToolBlockedOnUserSpan(
  _toolName?: string,
  _attrs?: Record<string, unknown>,
): Span {
  return NOOP_SPAN
}

export function endToolBlockedOnUserSpan(_span?: Span, _decision?: unknown): void {
  /* no-op */
}

export function addToolContentEvent(
  _span?: Span,
  _name?: string,
  _attrs?: Record<string, unknown>,
): void {
  /* no-op */
}

// ─── Hook + interaction lifecycles ─────────────────────────────────────────

export function startHookSpan(_hookName?: string, _attrs?: Record<string, unknown>): Span {
  return NOOP_SPAN
}

export function endHookSpan(_span?: Span, _result?: unknown): void {
  /* no-op */
}

export function startInteractionSpan(_attrs?: Record<string, unknown>): Span {
  return NOOP_SPAN
}
