// packages/core-shared/src/instrumentation/di/bind-noop-instrumentation.test.ts
import "reflect-metadata";
import { describe, it, expect } from "vitest";
import { Container } from "inversify";
import { bindNoopInstrumentation } from "@/instrumentation/di/bind-noop-instrumentation";
import { INSTRUMENTATION_SYMBOLS } from "@/instrumentation/symbols";
import { NoopTracer } from "@/instrumentation/noop-tracer";
import { NoopLogger } from "@/instrumentation/noop-logger";
import type { ITracer, ILogger } from "@/instrumentation";

describe("bindNoopInstrumentation", () => {
  it("returns a tracer + logger pair", () => {
    const c = new Container();
    const { tracer, logger } = bindNoopInstrumentation(c);
    expect(tracer).toBeInstanceOf(NoopTracer);
    expect(logger).toBeInstanceOf(NoopLogger);
  });

  it("binds TRACER and LOGGER symbols on the container", () => {
    const c = new Container();
    bindNoopInstrumentation(c);
    const tracer = c.get<ITracer>(INSTRUMENTATION_SYMBOLS.TRACER);
    const logger = c.get<ILogger>(INSTRUMENTATION_SYMBOLS.LOGGER);
    expect(tracer).toBeInstanceOf(NoopTracer);
    expect(logger).toBeInstanceOf(NoopLogger);
  });

  it("is idempotent — second call rebinds the same instances", () => {
    const c = new Container();
    const first = bindNoopInstrumentation(c);
    const second = bindNoopInstrumentation(c);
    // Implementations are NoopX, but instances may differ — that's fine
    expect(c.get(INSTRUMENTATION_SYMBOLS.TRACER)).toBe(second.tracer);
    expect(c.get(INSTRUMENTATION_SYMBOLS.LOGGER)).toBe(second.logger);
    expect(first.tracer).toBeInstanceOf(NoopTracer);
  });
});
