import { Logger } from '@nestjs/common';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { McpClientService } from './mcp-client.service.js';

const MCP_LEAK_MARKER = 'MCP_LEAK_MARKER /srv/secret';

describe('McpClientService — failed connect error sanitization', () => {
  const originalMcpServers = process.env['MCP_SERVERS'];

  beforeEach(() => {
    process.env['MCP_SERVERS'] = JSON.stringify([
      { name: 'leaky-server', url: 'http://localhost:9999/mcp' },
    ]);
  });

  afterEach(() => {
    vi.restoreAllMocks();
    if (originalMcpServers === undefined) {
      delete process.env['MCP_SERVERS'];
    } else {
      process.env['MCP_SERVERS'] = originalMcpServers;
    }
  });

  it('stores a generic serverEntry.error while logging the raw exception server-side', async () => {
    vi.spyOn(Client.prototype, 'connect').mockRejectedValue(new Error(MCP_LEAK_MARKER));
    const errorSpy = vi.spyOn(Logger.prototype, 'error').mockImplementation(() => undefined);

    const service = new McpClientService();
    await service.onModuleInit();

    const statuses = service.getServerStatuses();
    expect(statuses).toHaveLength(1);
    expect(statuses[0]?.connected).toBe(false);
    expect(statuses[0]?.error).toBe('Connection failed (see server logs).');
    expect(statuses[0]?.error).not.toContain(MCP_LEAK_MARKER);

    const loggedRawMarker = errorSpy.mock.calls.some((call) =>
      call.some((arg) => typeof arg === 'string' && arg.includes(MCP_LEAK_MARKER)),
    );
    expect(loggedRawMarker).toBe(true);
  });
});
