// ─── OpenTelemetry SDK Setup for Browser/Frontend ───
// Import this file BEFORE your app renders (e.g., at the top of main.tsx).
//
// Usage:
//   import './tracing';  // MUST be first import
//   import { createRoot } from 'react-dom/client';
//   // ... rest of app

import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { ZoneContextManager } from '@opentelemetry/context-zone';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
import { XMLHttpRequestInstrumentation } from '@opentelemetry/instrumentation-xml-http-request';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';

// Declare conformance to OTel Semantic Conventions v1.40.0 via schemaUrl.
// Downstream collectors (e.g., the Schema Translate Processor) can apply
// migration tables to rewrite attribute names across semconv versions —
// so even if upstream semconv drifts, emitted telemetry remains translatable.
// NOTE: @opentelemetry/resources 2.x removed the Resource class in favor of
// the `resourceFromAttributes` factory function.
const resource = resourceFromAttributes(
  {
    [ATTR_SERVICE_NAME]: '__SERVICE_NAME__',
  },
  { schemaUrl: 'https://opentelemetry.io/schemas/1.40.0' },
);

const exporter = new OTLPTraceExporter({
  url: '__OTLP_ENDPOINT__', // e.g., '/api/traces' or 'http://localhost:4318/v1/traces'
});

const provider = new WebTracerProvider({
  resource,
  spanProcessors: [new BatchSpanProcessor(exporter)],
});

// ZoneContextManager enables async context propagation in the browser
provider.register({
  contextManager: new ZoneContextManager(),
});

// Auto-instrument fetch and XHR
registerInstrumentations({
  instrumentations: [
    new FetchInstrumentation({
      // Only propagate trace headers to your own API (avoid CORS issues)
      propagateTraceHeaderCorsUrls: [/\/api\//],
      // Filter out static assets, HMR, etc.
      ignoreUrls: [/\.(js|css|png|jpg|svg|woff|map)$/, /hot-update/, /node_modules/],
    }),
    new XMLHttpRequestInstrumentation({
      propagateTraceHeaderCorsUrls: [/\/api\//],
    }),
  ],
});

// Export tracer for manual spans
export const tracer = provider.getTracer('__SERVICE_NAME__');

// ─── Utility wrappers ───

export async function withSpan<T>(
  name: string,
  fn: () => T | Promise<T>,
  attributes?: Record<string, string | number | boolean>
): Promise<T> {
  return tracer.startActiveSpan(name, { attributes }, async (span) => {
    try {
      return await fn();
    } catch (error) {
      span.recordException(error as Error);
      span.setStatus({ code: 2, message: (error as Error).message });
      throw error;
    } finally {
      span.end();
    }
  });
}
