// packages/core-shared/src/instrumentation/sentry/sentry-tracer.ts
import * as Sentry from "@sentry/nextjs";
import type { ITracer, ISpan, SpanOpts } from "../tracer.interface";

export class SentryTracer implements ITracer {
  async startSpan<T>(opts: SpanOpts, fn: (span: ISpan) => Promise<T>): Promise<T> {
    // Filter out null values — Sentry SpanAttributes doesn't allow null
    const attributes = opts.attributes
      ? Object.fromEntries(
          Object.entries(opts.attributes).filter(([, v]) => v !== null),
        ) as Record<string, string | number | boolean>
      : undefined;

    return Sentry.startSpan(
      {
        name: opts.name,
        op: opts.op,
        attributes,
      },
      async (sentrySpan) => {
        const adapter: ISpan = {
          setAttribute(key, value) {
            sentrySpan?.setAttribute?.(key, value as string | number | boolean);
          },
          setStatus(status, message) {
            // Sentry v8+ uses { code: number, message?: string }; we map our enum
            const code = status === "ok" ? 1 : 2;
            sentrySpan?.setStatus?.({ code, message });
          },
        };
        return fn(adapter);
      },
    );
  }
}
