import { jest } from '@jest/globals';
import { CSVLODContext } from '../../src/context.js';
import { CSVLODValidator } from '../../src/validator.js';
import { CSVLODGenerator } from '../../src/generator.js';
import { LocalMCPRegistry } from '../../src/registry.js';
import { SwarmCoordinator } from '../../src/swarm.js';
import * as fs from 'fs/promises';
import * as path from 'path';
import * as os from 'os';

describe('CSVLOD-AI Individual Tools Tests v3.0 - Corrected Interfaces', () => {
  let tempDir: string;
  
  beforeEach(async () => {
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'csvlod-test-'));
  });
  
  afterEach(async () => {
    await fs.rm(tempDir, { recursive: true, force: true });
  });

  describe('Tool 1: CSVLOD Context (csvlod_init)', () => {
    test('should initialize basic CSVLOD structure', async () => {
      const context = new CSVLODContext();
      const result = await context.initialize(tempDir, 'basic');
      
      expect(result).toBeDefined();
      expect(result.summary).toContain('CSVLOD');
      expect(result.filesCreated).toBeInstanceOf(Array);
      expect(result.filesCreated.length).toBeGreaterThan(0);
    });

    test('should complete initialization within performance target', async () => {
      const context = new CSVLODContext();
      const startTime = Date.now();
      
      await context.initialize(tempDir, 'minimal');
      
      const duration = Date.now() - startTime;
      expect(duration).toBeLessThan(2000); // 2 seconds
    });
  });

  describe('Tool 2: CSVLOD Validator (csvlod_validate)', () => {
    test('should validate CSVLOD compliance', async () => {
      // First initialize a project
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'basic');
      
      const validator = new CSVLODValidator();
      const result = await validator.validate(tempDir);
      
      expect(result).toBeDefined();
      expect(result.valid).toBeDefined();
      expect(result.score).toBeGreaterThanOrEqual(0);
      expect(result.issues).toBeInstanceOf(Array);
      expect(result.suggestions).toBeInstanceOf(Array);
    });

    test('should handle strict validation mode', async () => {
      const validator = new CSVLODValidator();
      const result = await validator.validate(tempDir, { strict: true });
      
      expect(result).toBeDefined();
      expect(result.valid).toBe(false); // Empty directory should fail validation
    });
  });

  describe('Tool 3: CSVLOD Generator (csvlod_generate)', () => {
    test('should generate context component', async () => {
      const generator = new CSVLODGenerator();
      const result = await generator.generate('context', tempDir);
      
      expect(result).toBeDefined();
             expect(result.filesGenerated).toBeInstanceOf(Array);
    });

    test('should generate manifest component', async () => {
      const generator = new CSVLODGenerator();
      const result = await generator.generate('manifest', tempDir);
      
      expect(result).toBeDefined();
             expect(result.filesGenerated).toBeInstanceOf(Array);
    });
  });

  describe('Tool 4: CSVLOD Analyzer (csvlod_analyze)', () => {
    test('should analyze context effectiveness', async () => {
      // First initialize a project
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'basic');
      
      const analysis = await context.analyze(tempDir);
      
      expect(analysis).toBeDefined();
      expect(analysis.score).toBeGreaterThanOrEqual(0);
      expect(analysis.strengths).toBeInstanceOf(Array);
      expect(analysis.improvements).toBeInstanceOf(Array);
    });

    test('should include detailed metrics when requested', async () => {
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'basic');
      
      const analysis = await context.analyze(tempDir, { includeMetrics: true });
      
      expect(analysis.metrics).toBeDefined();
      expect(analysis.metrics?.contextCoverage).toBeGreaterThanOrEqual(0);
    });
  });

  describe('Tool 5: MCP Registry (mcp_registry)', () => {
    let registry: LocalMCPRegistry;
    
    beforeEach(() => {
      registry = new LocalMCPRegistry();
    });

    test('should sync registry', async () => {
      const result = await registry.execute('sync');
      
      expect(result).toBeDefined();
      expect(result.success).toBe(true);
      expect(result.message).toContain('sync');
    });

    test('should search registry', async () => {
      const result = await registry.execute('search', { query: 'test' });
      
      expect(result).toBeDefined();
      expect(result.success).toBe(true);
      expect(result.message).toContain('search');
      expect(result.data).toBeDefined();
    });

    test('should install from registry', async () => {
      const result = await registry.execute('install', { query: 'test-server' });
      
      expect(result).toBeDefined();
      expect(result.success).toBe(true);
      expect(result.message).toContain('install');
    });

    test('should list registry contents', async () => {
      const result = await registry.execute('list');
      
      expect(result).toBeDefined();
      expect(result.success).toBe(true);
      expect(result.message).toContain('list');
      expect(result.data).toBeDefined();
    });

    test('should handle local-only mode', async () => {
      const result = await registry.execute('sync', { localOnly: true });
      
      expect(result).toBeDefined();
      expect(result.success).toBe(true);
      expect(result.message).toContain('local');
    });
  });

  describe('Tool 6: MCP Orchestrator (mcp_orchestrate)', () => {
    test('should create orchestration plan', async () => {
      const registry = new LocalMCPRegistry();
      const result = await registry.orchestrate('Test task');
      
      expect(result).toBeDefined();
      expect(result.task).toBeDefined();
      expect(result.servers).toBeInstanceOf(Array);
      expect(result.executionOrder).toBeInstanceOf(Array);
      expect(result.isLocal).toBeDefined();
      expect(result.estimatedTime).toBeDefined();
    });

    test('should handle preferLocal option', async () => {
      const registry = new LocalMCPRegistry();
      const result = await registry.orchestrate('Test task', { preferLocal: true });
      
      expect(result).toBeDefined();
      expect(result.isLocal).toBe(true);
    });

    test('should handle ephemeral instances', async () => {
      const registry = new LocalMCPRegistry();
      const result = await registry.orchestrate('Test task', { ephemeral: true });
      
      expect(result).toBeDefined();
      expect(result.servers.some(s => s.isEphemeral)).toBe(true);
    });
  });

  describe('Agent Swarm Coordination', () => {
    let swarmCoordinator: SwarmCoordinator;
    
    beforeEach(async () => {
      // Create a basic CSVLOD structure first
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'basic');
      
      swarmCoordinator = new SwarmCoordinator(path.join(tempDir, '.csvlod', 'AGENT-MANIFEST.yaml'));
    });

    test('should initialize swarm coordination', async () => {
      const status = swarmCoordinator.getSwarmStatus();
      
      expect(status).toBeDefined();
      expect(status.swarm_enabled).toBeDefined();
      expect(status.coordination_mode).toBeDefined();
      expect(status.active_agents).toBeDefined();
      expect(status.task_counts).toBeDefined();
      expect(status.total_tasks).toBeDefined();
      expect(status.context_cache_size).toBeDefined();
    });

    test('should decompose tasks', async () => {
             const tasks = await swarmCoordinator.decomposeTask('Complex development task', ['backend', 'frontend']);
      
      expect(tasks).toBeInstanceOf(Array);
      expect(tasks.length).toBeGreaterThan(0);
      
      tasks.forEach(task => {
        expect(task.id).toBeDefined();
        expect(task.agent_type).toBeDefined();
        expect(task.description).toBeDefined();
        expect(task.status).toBe('pending');
      });
    });

    test('should handle task assignment', async () => {
      const tasks = await swarmCoordinator.decomposeTasks('Test task', ['test']);
      const taskId = tasks[0].id;
      
      const assignedAgent = await swarmCoordinator.assignTask(taskId);
      
      if (assignedAgent) {
        expect(assignedAgent).toContain('test-');
        
        const updatedStatus = swarmCoordinator.getSwarmStatus();
        expect(updatedStatus.task_counts.in_progress).toBeGreaterThan(0);
      }
    });

    test('should complete tasks', async () => {
      const tasks = await swarmCoordinator.decomposeTasks('Test task', ['test']);
      const taskId = tasks[0].id;
      
      await swarmCoordinator.assignTask(taskId);
      await swarmCoordinator.completeTask(taskId, { result: 'Test completed' });
      
      const taskDetails = swarmCoordinator.getTaskDetails(taskId);
      expect(taskDetails).not.toBeNull();
      if (taskDetails) {
        expect(taskDetails.status).toBe('completed');
        expect(taskDetails.result).toBeDefined();
      }
    });

    test('should provide task details', async () => {
      const tasks = await swarmCoordinator.decomposeTasks('Test task', ['test']);
      const taskId = tasks[0].id;
      
      const taskDetails = swarmCoordinator.getTaskDetails(taskId);
      
      expect(taskDetails).not.toBeNull();
      if (taskDetails) {
        expect(taskDetails.id).toBe(taskId);
        expect(taskDetails.agent_type).toBe('test');
        expect(taskDetails.description).toContain('Test task');
      }
    });
  });

  describe('Performance Benchmarks', () => {
    test('should meet initialization performance targets', async () => {
      const context = new CSVLODContext();
      const startTime = Date.now();
      
      await context.initialize(tempDir, 'basic');
      
      const duration = Date.now() - startTime;
      expect(duration).toBeLessThan(2000); // 2 seconds for basic initialization
    });

    test('should meet validation performance targets', async () => {
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'basic');
      
      const validator = new CSVLODValidator();
      const startTime = Date.now();
      
      await validator.validate(tempDir);
      
      const duration = Date.now() - startTime;
      expect(duration).toBeLessThan(1000); // 1 second for validation
    });

    test('should meet analysis performance targets', async () => {
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'basic');
      
      const startTime = Date.now();
      await context.analyze(tempDir);
      
      const duration = Date.now() - startTime;
      expect(duration).toBeLessThan(1500); // 1.5 seconds for analysis
    });
  });
}); 