import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { AtlasServer } from '../server.js';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

// Mock the dashboard server module to prevent database initialization
vi.mock('../web-dashboard/server.js', () => ({
  DashboardServer: vi.fn().mockImplementation(() => ({
    start: vi.fn().mockResolvedValue(undefined),
    stop: vi.fn().mockResolvedValue(undefined),
    getUrl: vi.fn().mockReturnValue('http://localhost:3001'),
    isHealthy: vi.fn().mockReturnValue(true),
    getConfig: vi.fn().mockReturnValue({
      enabled: false,
      port: 3001,
      host: 'localhost'
    })
  }))
}));

// Mock the SQLite manager to prevent database initialization
vi.mock('../storage/sqlite-manager.js', () => ({
  getSQLiteManager: vi.fn(() => ({
    initialize: vi.fn().mockResolvedValue(true),
    close: vi.fn().mockResolvedValue(true),
    query: vi.fn().mockResolvedValue({ success: true, data: [] }),
    get: vi.fn().mockResolvedValue({ success: true, data: null }),
    run: vi.fn().mockResolvedValue({ success: true, data: { changes: 1 } })
  })),
  ensureDatabaseReady: vi.fn().mockResolvedValue({
    getConnectionInfo: () => ({
      isInitialized: true,
      dbPath: ':memory:'
    })
  }),
  SQLiteManager: vi.fn()
}));

// Mock data migration
vi.mock('../storage/data-migration.js', () => ({
  autoMigrateOnStartup: vi.fn().mockResolvedValue(undefined)
}));

describe('AtlasServer', () => {
  let server: AtlasServer;
  let client: Client;
  let serverTransport: InMemoryTransport;
  let clientTransport: InMemoryTransport;

  beforeEach(async () => {
    // Set NODE_ENV to test to ensure test configuration is used
    process.env.NODE_ENV = 'test';
    process.env.ATLAS_DASHBOARD_ENABLED = 'false'; // Disable dashboard in tests
    
    server = new AtlasServer();
    
    // Initialize server (this will register modules)
    await (server as any).initialize();
    
    // Create in-memory transports for testing
    const transports = InMemoryTransport.createLinkedPair();
    serverTransport = transports[0];
    clientTransport = transports[1];
    
    // Connect server with in-memory transport instead of stdio
    const serverReady = (server as any).server.connect(serverTransport);
    
    // Connect client
    client = new Client({
      name: 'test-client',
      version: '1.0.0',
    }, {
      capabilities: {},
    });
    const clientReady = client.connect(clientTransport);
    
    // Wait for both to be ready
    await Promise.all([serverReady, clientReady]);
  });
  
  afterEach(async () => {
    await client.close();
    await (server as any).server.close();
  });

  describe('Initialization', () => {
    it('should create server with correct name and version', async () => {
      // Check that the server was created
      expect(server).toBeDefined();
      expect((server as any).server).toBeDefined();
    });

    it('should register required capabilities', async () => {
      // Capabilities are registered when modules are loaded
      expect((server as any).server).toBeDefined();
      // The actual capability check would be done through client requests
    });
  });

  describe('Tool Registration', () => {
    it('should register core tools', async () => {
      const response = await client.listTools();
      expect(response.tools).toBeDefined();
      expect(response.tools.length).toBeGreaterThan(0);
      
      // Check for specific tools from migrated modules
      const toolNames = response.tools.map((t: any) => t.name);
      // Tools are namespaced with module names
      expect(toolNames).toContain('kanban--create_kanban_board');
      expect(toolNames).toContain('kanban--create_kanban_task');
      expect(toolNames).toContain('workspace--create_workspace');
      expect(toolNames).toContain('development--create_feature');
      expect(toolNames).toContain('agile-management--create_user_story');
    });
  });

  describe('Resource Registration', () => {
    it('should register core resources', async () => {
      const response = await client.listResources();
      expect(response.resources).toBeDefined();
      expect(response.resources.length).toBeGreaterThan(0);
      
      // Check for specific resources
      const resourceUris = response.resources.map((r: any) => r.uri);
      expect(resourceUris).toContain('atlas://dashboard');
      expect(resourceUris).toContain('atlas://database/stats');
      expect(resourceUris).toContain('atlas://tools/manifest');
    });
  });

  describe('Prompt Registration', () => {
    it('should not register prompts in this architecture', async () => {
      // The 12-factor architecture doesn't use prompts
      // This is handled by the tool-based approach instead
      expect(true).toBe(true);
    });
  });

  describe('Module Integration', () => {
    it('should integrate kanban module tools', async () => {
      const response = await client.listTools();
      
      // Check for kanban-specific tools  
      const toolNames = response.tools.map((t: any) => t.name);
      expect(toolNames).toContain('kanban--create_kanban_board');
      expect(toolNames).toContain('kanban--move_kanban_task');
    });

    it('should integrate development module tools', async () => {
      const response = await client.listTools();
      
      // Check for development-specific tools
      const toolNames = response.tools.map((t: any) => t.name);
      expect(toolNames).toContain('development--create_feature'); // from development module
      expect(toolNames).toContain('developer-workflow--start_feature'); // from developer-workflow module
      expect(toolNames).toContain('development--write_test'); // from development module
      expect(toolNames).toContain('development--run_tests'); // from development module
      expect(toolNames).toContain('development--enforce_tdd'); // from development module
    });
  });
});