import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { ConsoleSpanExporter } from '@opentelemetry/sdk-trace-base';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { findMetricValue } from '../../__fixtures__/metrics-helpers.js';
vi.mock('@opentelemetry/exporter-trace-otlp-http', () => ({
    OTLPTraceExporter: vi.fn(),
}));
vi.mock('@opentelemetry/sdk-trace-base', async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        ConsoleSpanExporter: vi.fn(),
    };
});
// resetModules clears the module cache so each test gets a fresh singleton.
// Tests use dynamic await import() to re-import after the reset.
describe('setupTracer (node-specific)', () => {
    const originalEnv = { ...process.env };
    beforeEach(() => {
        vi.resetModules();
        vi.clearAllMocks();
    });
    afterEach(() => {
        process.env = { ...originalEnv };
    });
    describe('provider auto-detection', () => {
        it('should use NodeTracerProvider by default for async context support', async () => {
            const telemetry = await import('../index.js');
            const provider = telemetry.setupTracer();
            expect(provider).toBeInstanceOf(NodeTracerProvider);
        });
        it('should accept a custom NodeTracerProvider', async () => {
            const telemetry = await import('../index.js');
            const customProvider = new NodeTracerProvider();
            const provider = telemetry.setupTracer({ provider: customProvider });
            expect(provider).toBe(customProvider);
        });
    });
    describe('exporter configuration', () => {
        it('should add OTLP exporter when exporters.otlp is true', async () => {
            const telemetry = await import('../index.js');
            telemetry.setupTracer({ exporters: { otlp: true } });
            expect(OTLPTraceExporter).toHaveBeenCalled();
        });
        it('should add console exporter when exporters.console is true', async () => {
            const telemetry = await import('../index.js');
            telemetry.setupTracer({ exporters: { console: true } });
            expect(ConsoleSpanExporter).toHaveBeenCalled();
        });
        it('should add both exporters when both are true', async () => {
            const telemetry = await import('../index.js');
            telemetry.setupTracer({ exporters: { otlp: true, console: true } });
            expect(OTLPTraceExporter).toHaveBeenCalled();
            expect(ConsoleSpanExporter).toHaveBeenCalled();
        });
        it('should add no exporters when both are false', async () => {
            const telemetry = await import('../index.js');
            telemetry.setupTracer({ exporters: { otlp: false, console: false } });
            expect(OTLPTraceExporter).not.toHaveBeenCalled();
            expect(ConsoleSpanExporter).not.toHaveBeenCalled();
        });
        it('should add no exporters when exporters config is empty', async () => {
            const telemetry = await import('../index.js');
            telemetry.setupTracer({});
            expect(OTLPTraceExporter).not.toHaveBeenCalled();
            expect(ConsoleSpanExporter).not.toHaveBeenCalled();
        });
    });
    describe('resource attributes from environment', () => {
        it('should use OTEL_SERVICE_NAME when set', async () => {
            process.env.OTEL_SERVICE_NAME = 'my-custom-service';
            const telemetry = await import('../index.js');
            const provider = telemetry.setupTracer();
            expect(provider['_resource'].attributes['service.name']).toBe('my-custom-service');
        });
        it('should use OTEL_SERVICE_NAMESPACE when set', async () => {
            process.env.OTEL_SERVICE_NAMESPACE = 'my-namespace';
            const telemetry = await import('../index.js');
            const provider = telemetry.setupTracer();
            expect(provider['_resource'].attributes['service.namespace']).toBe('my-namespace');
        });
        it('should use OTEL_DEPLOYMENT_ENVIRONMENT when set', async () => {
            process.env.OTEL_DEPLOYMENT_ENVIRONMENT = 'production';
            const telemetry = await import('../index.js');
            const provider = telemetry.setupTracer();
            expect(provider['_resource'].attributes['deployment.environment']).toBe('production');
        });
        it('should merge OTEL_RESOURCE_ATTRIBUTES with defaults', async () => {
            process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.version=1.0.0,custom.team=platform';
            const telemetry = await import('../index.js');
            const provider = telemetry.setupTracer();
            expect(provider['_resource'].attributes['service.version']).toBe('1.0.0');
            expect(provider['_resource'].attributes['custom.team']).toBe('platform');
            expect(provider['_resource'].attributes['service.name']).toBe('strands-agents');
        });
        it('should allow OTEL_RESOURCE_ATTRIBUTES to override defaults', async () => {
            process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=custom-service,deployment.environment=production';
            const telemetry = await import('../index.js');
            const provider = telemetry.setupTracer();
            expect(provider['_resource'].attributes['service.name']).toBe('custom-service');
            expect(provider['_resource'].attributes['deployment.environment']).toBe('production');
        });
    });
});
describe('setupMeter (node-specific)', () => {
    const originalEnv = { ...process.env };
    beforeEach(() => {
        vi.resetModules();
        vi.clearAllMocks();
    });
    afterEach(() => {
        process.env = { ...originalEnv };
    });
    describe('resource attributes from environment', () => {
        it('should use OTEL_SERVICE_NAME when set', async () => {
            process.env.OTEL_SERVICE_NAME = 'my-meter-service';
            const { MeterProvider, InMemoryMetricExporter, PeriodicExportingMetricReader, AggregationTemporality } = await import('@opentelemetry/sdk-metrics');
            const { resourceFromAttributes } = await import('@opentelemetry/resources');
            const telemetry = await import('../index.js');
            const exporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
            const reader = new PeriodicExportingMetricReader({ exporter, exportIntervalMillis: 100 });
            const customProvider = new MeterProvider({
                resource: resourceFromAttributes({ 'service.name': 'my-meter-service' }),
                readers: [reader],
            });
            const provider = telemetry.setupMeter({ provider: customProvider });
            provider.getMeter('test').createCounter('probe').add(1);
            await provider.forceFlush();
            const resource = exporter.getMetrics().at(-1)?.resource;
            expect(resource?.attributes['service.name']).toBe('my-meter-service');
            await provider.shutdown();
        });
    });
    describe('global meter provider registration', () => {
        it('returns a provider that produces real metrics via its own meter', async () => {
            const { MeterProvider: SdkMeterProvider, InMemoryMetricExporter, PeriodicExportingMetricReader, AggregationTemporality, } = await import('@opentelemetry/sdk-metrics');
            const telemetry = await import('../index.js');
            const testExporter = new InMemoryMetricExporter(AggregationTemporality.CUMULATIVE);
            const testReader = new PeriodicExportingMetricReader({
                exporter: testExporter,
                exportIntervalMillis: 100,
            });
            const testProvider = new SdkMeterProvider({ readers: [testReader] });
            const provider = telemetry.setupMeter({ provider: testProvider });
            const meter = provider.getMeter('test-registration');
            const counter = meter.createCounter('test_registration_counter');
            counter.add(42);
            await testProvider.forceFlush();
            expect(findMetricValue(testExporter.getMetrics(), 'test_registration_counter')).toBe(42);
            await testProvider.shutdown();
        });
    });
    describe('custom provider', () => {
        it('accepts a custom MeterProvider', async () => {
            const { MeterProvider } = await import('@opentelemetry/sdk-metrics');
            const telemetry = await import('../index.js');
            const customProvider = new MeterProvider();
            const provider = telemetry.setupMeter({ provider: customProvider });
            expect(provider).toBe(customProvider);
        });
    });
});
//# sourceMappingURL=config.test.node.js.map