import { describe, it, expect } from 'vitest';
import { generateMcpConfig } from '../src/services/mcp-config-generator.js';
import type { McpServer } from '@prisma/client';

function makeServer(overrides: Partial<McpServer> = {}): McpServer {
  return {
    id: 's1',
    name: 'slack',
    description: 'Slack MCP',
    packageName: '@anthropic/slack-mcp',
    dockerImage: null,
    transport: 'STDIO',
    repositoryUrl: null,
    externalUrl: null,
    command: null,
    containerPort: null,
    replicas: 1,
    env: [],
    healthCheck: null,
    version: 1,
    createdAt: new Date(),
    updatedAt: new Date(),
    templateName: null,
    templateVersion: null,
    ...overrides,
  };
}

describe('generateMcpConfig', () => {
  it('returns empty mcpServers for empty input', () => {
    const result = generateMcpConfig([]);
    expect(result).toEqual({ mcpServers: {} });
  });

  it('generates config for a single STDIO server', () => {
    const result = generateMcpConfig([
      { server: makeServer(), resolvedEnv: {} },
    ]);
    expect(result.mcpServers['slack']).toBeDefined();
    expect(result.mcpServers['slack']?.command).toBe('npx');
    expect(result.mcpServers['slack']?.args).toEqual(['-y', '@anthropic/slack-mcp']);
  });

  it('includes resolved env when present for STDIO server', () => {
    const result = generateMcpConfig([
      { server: makeServer(), resolvedEnv: { SLACK_TEAM_ID: 'T123' } },
    ]);
    const config = result.mcpServers['slack'];
    expect(config?.env).toBeDefined();
    expect(config?.env?.['SLACK_TEAM_ID']).toBe('T123');
  });

  it('omits env when resolvedEnv is empty', () => {
    const result = generateMcpConfig([
      { server: makeServer(), resolvedEnv: {} },
    ]);
    expect(result.mcpServers['slack']?.env).toBeUndefined();
  });

  it('generates multiple server configs', () => {
    const result = generateMcpConfig([
      { server: makeServer({ name: 'slack' }), resolvedEnv: {} },
      { server: makeServer({ name: 'github', id: 's2', packageName: '@anthropic/github-mcp' }), resolvedEnv: {} },
    ]);
    expect(Object.keys(result.mcpServers)).toHaveLength(2);
    expect(result.mcpServers['slack']).toBeDefined();
    expect(result.mcpServers['github']).toBeDefined();
  });

  it('uses server name as fallback when packageName is null', () => {
    const server = makeServer({ packageName: null });
    const result = generateMcpConfig([
      { server, resolvedEnv: {} },
    ]);
    expect(result.mcpServers['slack']?.args).toEqual(['-y', 'slack']);
  });

  it('generates URL-based config for SSE servers', () => {
    const server = makeServer({ name: 'sse-server', transport: 'SSE' });
    const result = generateMcpConfig([
      { server, resolvedEnv: { TOKEN: 'abc' } },
    ]);
    const config = result.mcpServers['sse-server'];
    expect(config?.url).toBe('http://localhost:3100/api/v1/mcp/proxy/sse-server');
    expect(config?.command).toBeUndefined();
    expect(config?.args).toBeUndefined();
    expect(config?.env).toBeUndefined();
  });

  it('generates URL-based config for STREAMABLE_HTTP servers', () => {
    const server = makeServer({ name: 'stream-server', transport: 'STREAMABLE_HTTP' });
    const result = generateMcpConfig([
      { server, resolvedEnv: {} },
    ]);
    const config = result.mcpServers['stream-server'];
    expect(config?.url).toBe('http://localhost:3100/api/v1/mcp/proxy/stream-server');
    expect(config?.command).toBeUndefined();
  });

  it('mixes STDIO and SSE servers correctly', () => {
    const result = generateMcpConfig([
      { server: makeServer({ name: 'stdio-srv', transport: 'STDIO' }), resolvedEnv: {} },
      { server: makeServer({ name: 'sse-srv', transport: 'SSE' }), resolvedEnv: {} },
    ]);
    expect(result.mcpServers['stdio-srv']?.command).toBe('npx');
    expect(result.mcpServers['sse-srv']?.url).toBeDefined();
  });
});
