import { vi } from "vitest";

/**
 * Guard against real Sentry SDK + OTel SDK initialization in test processes.
 *
 * Mocks @sentry/* and key @opentelemetry/sdk-* modules at the module level so
 * any code that imports them receives a no-op surface. Tests that need to assert
 * specific SDK behavior still use vi.mock locally with their own implementation;
 * this guard just ensures *unintentional* imports don't cause real network/init.
 *
 * Also exported as ./setup/no-sentry for one release cycle (backward-compat alias).
 */
vi.mock("@sentry/nextjs", () => ({
  init: vi.fn(),
  startSpan: vi.fn((_opts: unknown, fn: (span: unknown) => unknown) =>
    fn({ setAttribute: vi.fn(), setStatus: vi.fn() }),
  ),
  captureException: vi.fn(),
  captureMessage: vi.fn(),
  addBreadcrumb: vi.fn(),
  setUser: vi.fn(),
  setContext: vi.fn(),
  setTag: vi.fn(),
  setExtra: vi.fn(),
  withScope: vi.fn((fn: (scope: unknown) => unknown) =>
    fn({ setTag: vi.fn(), setExtra: vi.fn() }),
  ),
  replayIntegration: vi.fn(() => ({ name: "Replay" })),
  getActiveSpan: vi.fn(() => undefined),
  getCurrentHub: vi.fn(() => ({ getClient: () => undefined })),
}));

vi.mock("@sentry/node", () => ({
  init: vi.fn(),
  startSpan: vi.fn((_opts: unknown, fn: (span: unknown) => unknown) =>
    fn({ setAttribute: vi.fn(), setStatus: vi.fn() }),
  ),
  captureException: vi.fn(),
  captureMessage: vi.fn(),
  addBreadcrumb: vi.fn(),
  setUser: vi.fn(),
  setContext: vi.fn(),
  setTag: vi.fn(),
  setExtra: vi.fn(),
  withScope: vi.fn((fn: (scope: unknown) => unknown) =>
    fn({ setTag: vi.fn(), setExtra: vi.fn() }),
  ),
  getActiveSpan: vi.fn(() => undefined),
}));

vi.mock("@sentry/react", () => ({
  init: vi.fn(),
  captureException: vi.fn(),
  captureMessage: vi.fn(),
  addBreadcrumb: vi.fn(),
  setUser: vi.fn(),
  setContext: vi.fn(),
  setTag: vi.fn(),
  setExtra: vi.fn(),
  withScope: vi.fn((fn: (scope: unknown) => unknown) =>
    fn({ setTag: vi.fn(), setExtra: vi.fn() }),
  ),
  replayIntegration: vi.fn(() => ({ name: "Replay" })),
}));

// OTel SDK mocks — prevent real SDK initialization in vitest runs.
// Feature packages and core-shared instrumentation code import these; without
// mocks the NodeSDK would attempt to bootstrap a real tracer/logger provider.
vi.mock("@opentelemetry/sdk-node", () => ({
  NodeSDK: class {
    start() {}
    shutdown() {
      return Promise.resolve();
    }
  },
  // Re-export tracing namespace so destructured imports work
  tracing: {
    BatchSpanProcessor: class {
      onStart() {}
      onEnd() {}
      forceFlush() {
        return Promise.resolve();
      }
      shutdown() {
        return Promise.resolve();
      }
    },
  },
}));

vi.mock("@sentry/opentelemetry", () => ({
  SentrySpanProcessor: class {
    onStart() {}
    onEnd() {}
    forceFlush() {
      return Promise.resolve();
    }
    shutdown() {
      return Promise.resolve();
    }
  },
  // SentryLogRecordProcessor does NOT exist in @sentry/opentelemetry v10 — omitted.
  // No-op Sentry.init wrapper used by sentry-bridge.ts
  init: vi.fn(),
}));
