/**
 * OpenTelemetry SDK bootstrap for the SPA (per ADR-0012, phase 2).
 *
 * Symmetrical to apps/portal-bff/src/observability/tracing.ts — must
 * be the very first import in `main.ts` so the auto-instrumentations
 * patch `fetch` / `XMLHttpRequest` / `addEventListener` before any
 * application code runs.
 *
 * What this enables out of the box
 * ────────────────────────────────
 * - `document_load` span on first paint, capturing every Performance
 *   Timing API metric (DNS, TLS, request, response, DOM events).
 * - `fetch` spans for every outgoing request, with the W3C
 *   `traceparent` header propagated so the BFF picks up the same
 *   trace id and produces a child span. The result in Jaeger is one
 *   end-to-end trace SPA → BFF → DB.
 * - `user_interaction` spans for click / keypress events on
 *   instrumented elements.
 *
 * Notes on the zoneless setup
 * ───────────────────────────
 * Angular here is zoneless (per ADR-0004), so we deliberately do NOT
 * pull in `@opentelemetry/context-zone`. The default
 * `StackContextManager` baked into `@opentelemetry/sdk-trace-web` is
 * sufficient: the auto-instrumentations capture context at patch
 * time and propagate it across the boundaries they own (fetch
 * lifecycle, event handlers). Custom spans across `await` will need
 * explicit `context.with(...)` plumbing — fine, encountered as code
 * lands.
 *
 * Endpoint configuration
 * ──────────────────────
 * The OTLP/HTTP endpoint and the BFF origin both come from
 * `src/environments/environment.ts` (per ADR-0018). Per-environment
 * siblings of that file ship under `fileReplacements`.
 */

import { WebTracerProvider, BatchSpanProcessor } from '@opentelemetry/sdk-trace-web';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
import { DocumentLoadInstrumentation } from '@opentelemetry/instrumentation-document-load';
import { UserInteractionInstrumentation } from '@opentelemetry/instrumentation-user-interaction';

import { environment } from '../environments/environment';

const SERVICE_NAME = 'portal-shell';
// Static for now; a follow-up wires this to the build-time version
// (same source as the footer's dev-only version badge).
const SERVICE_VERSION = 'dev';

// Derive the trace-header propagation pattern from the BFF base URL
// so a deploy-time change to `bffApiBaseUrl` automatically propagates
// `traceparent` to the right origin. RegExp special chars are escaped
// before going into the source.
const bffOrigin = new URL(environment.bffApiBaseUrl).origin;
const bffOriginRegex = new RegExp(`^${bffOrigin.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}/.*`);

const provider = new WebTracerProvider({
  resource: resourceFromAttributes({
    [ATTR_SERVICE_NAME]: SERVICE_NAME,
    [ATTR_SERVICE_VERSION]: SERVICE_VERSION,
  }),
  spanProcessors: [
    new BatchSpanProcessor(new OTLPTraceExporter({ url: environment.otlpEndpoint })),
  ],
});

provider.register();

registerInstrumentations({
  instrumentations: [
    // Times the initial page load — fires once.
    new DocumentLoadInstrumentation(),
    // Wraps every `fetch` call. Propagates `traceparent` to the BFF
    // origin derived from the environment.
    new FetchInstrumentation({
      propagateTraceHeaderCorsUrls: [bffOriginRegex],
    }),
    // Auto-spans on click / keypress / submit (and a small allow-list
    // beyond that). Quiet in dev, useful in staging perf
    // investigations.
    new UserInteractionInstrumentation(),
  ],
});
