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 { createSwarmCoordinator } from '../../src/swarm.js';
import fs from 'fs/promises';
import path from 'path';
import os from 'os';

describe('End-to-End Integration Tests', () => {
  let tempDir: string;
  
  beforeEach(async () => {
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'csvlod-e2e-'));
  });

  afterEach(async () => {
    try {
      await fs.rm(tempDir, { recursive: true, force: true });
    } catch (error) {
      // Ignore cleanup errors
    }
  });

  describe('Complete Project Setup Workflow', () => {
    test('should complete full project initialization and validation cycle', async () => {
      // Step 1: Initialize CSVLOD structure
      const context = new CSVLODContext();
      const initResult = await context.initialize(tempDir, 'basic');
      
      expect(initResult.filesCreated.length).toBeGreaterThan(0);
      
      // Step 2: Validate the created structure
      const validator = new CSVLODValidator();
      const validationResult = await validator.validate(tempDir, { strict: false });
      
      expect(validationResult.score).toBeGreaterThan(0);
      expect(validationResult.valid).toBe(true);
      
      // Step 3: Analyze context effectiveness
      const analysisResult = await context.analyze(tempDir, { includeMetrics: true });
      
      expect(analysisResult.score).toBeGreaterThan(0);
      expect(analysisResult.recommendations).toBeInstanceOf(Array);
      
      // Step 4: Generate additional components
      const generator = new CSVLODGenerator();
      const generatedPrompt = await generator.generate('prompt', tempDir);
      
      expect(generatedPrompt.outputPath).toBeDefined();
      
      // Step 5: Re-validate after generation
      const finalValidation = await validator.validate(tempDir, { strict: false });
      
      expect(finalValidation.score).toBeGreaterThanOrEqual(validationResult.score);
    });

    test('should handle enterprise project workflow', async () => {
      // Enterprise workflow with more complex requirements
      const context = new CSVLODContext();
      const initResult = await context.initialize(tempDir, 'enterprise');
      
      expect(initResult.filesCreated.length).toBeGreaterThan(0);
      expect(initResult.summary).toContain('enterprise');
      
      // Generate multiple components for enterprise setup
      const generator = new CSVLODGenerator();
      const components = ['context', 'manifest', 'structure'];
      
      for (const component of components) {
        const result = await generator.generate(component, tempDir, {
          framework: 'enterprise',
          aiTools: true
        });
        expect(result.outputPath).toBeDefined();
      }
      
      // Strict validation for enterprise
      const validator = new CSVLODValidator();
      const validation = await validator.validate(tempDir, { strict: true });
      
      expect(validation).toBeDefined();
      expect(validation.issues).toBeInstanceOf(Array);
    });
  });

  describe('Agent Swarm Coordination Workflow', () => {
    test('should complete full swarm coordination lifecycle', async () => {
      // Step 1: Initialize project
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'enterprise');
      
      // Step 2: Initialize swarm coordination
      const coordinator = await createSwarmCoordinator(tempDir);
      const initialStatus = coordinator.getSwarmStatus();
      
      expect(initialStatus.agents.length).toBeGreaterThan(0);
      
      // Step 3: Decompose a complex task
      const tasks = await coordinator.decomposeTask(
        'Implement complete user authentication system with security audit and documentation',
        tempDir,
        ['principles', 'standards', 'designs']
      );
      
      expect(tasks.length).toBeGreaterThan(1);
      
      // Step 4: Assign tasks to agents
      const assignments = [];
      for (const task of tasks) {
        const agentId = await coordinator.assignTask(task.id);
        if (agentId) {
          assignments.push({ taskId: task.id, agentId });
        }
      }
      
      expect(assignments.length).toBeGreaterThan(0);
      
      // Step 5: Complete some tasks
      for (const assignment of assignments.slice(0, 2)) {
        await coordinator.completeTask(assignment.taskId, {
          status: 'success',
          output: `Task ${assignment.taskId} completed by ${assignment.agentId}`,
          files_modified: [`${tempDir}/output_${assignment.taskId}.md`]
        });
      }
      
      // Step 6: Check final status
      const finalStatus = coordinator.getSwarmStatus();
      expect(finalStatus.task_counts.completed).toBeGreaterThan(0);
    });

    test('should handle task dependencies correctly', async () => {
      const context = new CSVLODContext();
      await context.initialize(tempDir, 'enterprise');
      
      const coordinator = await createSwarmCoordinator(tempDir);
      
      // Create tasks with complex dependencies
      const tasks = await coordinator.decomposeTask(
        'Database design -> API development -> Frontend integration -> Testing -> Deployment',
        tempDir,
        ['principles', 'standards', 'designs']
      );
      
      // Verify dependency chain handling
      let completedTasks = 0;
      let maxIterations = 10;
      
      while (completedTasks < tasks.length && maxIterations > 0) {
        for (const task of tasks) {
          const taskDetails = coordinator.getTaskDetails(task.id);
          if (taskDetails && taskDetails.status === 'pending') {
            const agentId = await coordinator.assignTask(task.id);
            if (agentId) {
              await coordinator.completeTask(task.id, {
                status: 'success',
                output: `Dependency task completed: ${task.description}`,
                files_modified: []
              });
              completedTasks++;
            }
          }
        }
        maxIterations--;
      }
      
      const finalStatus = coordinator.getSwarmStatus();
      expect(finalStatus.task_counts.completed).toBeGreaterThan(0);
    });
  });

  describe('MCP Registry Integration Workflow', () => {
    test('should complete registry sync and orchestration workflow', async () => {
      const registry = new LocalMCPRegistry();
      
      // Step 1: Sync registry
      const syncResult = await registry.execute('sync', {});
      expect(syncResult.action).toBe('sync');
      
      // Step 2: Search for packages
      const searchResult = await registry.execute('search', { 
        query: 'context-engineering' 
      });
      expect(searchResult.action).toBe('search');
      expect(searchResult.results).toBeInstanceOf(Array);
      
      // Step 3: List available packages
      const listResult = await registry.execute('list', {});
      expect(listResult.action).toBe('list');
      expect(listResult.packages).toBeInstanceOf(Array);
      
      // Step 4: Create orchestration plan
      const orchestration = await registry.orchestrate(
        'Setup development environment with testing and deployment tools',
        { preferLocal: true, ephemeral: false }
      );
      
      expect(orchestration.task).toBeDefined();
      expect(orchestration.plan).toBeDefined();
    });
  });

  describe('Performance Integration Tests', () => {
    test('should meet performance targets in complete workflow', async () => {
      const startTime = Date.now();
      
      // Complete workflow under performance constraints
      const context = new CSVLODContext();
      const initStart = Date.now();
      const initResult = await context.initialize(tempDir, 'basic');
      const initDuration = Date.now() - initStart;
      
      // Initialization should be fast
      expect(initDuration).toBeLessThan(5000); // 5 seconds
      
      const validateStart = Date.now();
      const validator = new CSVLODValidator();
      const validation = await validator.validate(tempDir, { strict: false });
      const validateDuration = Date.now() - validateStart;
      
      // Validation should be fast
      expect(validateDuration).toBeLessThan(3000); // 3 seconds
      
      const analyzeStart = Date.now();
      const analysis = await context.analyze(tempDir, { includeMetrics: true });
      const analyzeDuration = Date.now() - analyzeStart;
      
      // Analysis should be reasonable
      expect(analyzeDuration).toBeLessThan(5000); // 5 seconds
      
      const totalDuration = Date.now() - startTime;
      
      // Total workflow should complete within reasonable time
      expect(totalDuration).toBeLessThan(15000); // 15 seconds total
      
      // Verify quality wasn't sacrificed for speed
      expect(initResult.filesCreated.length).toBeGreaterThan(0);
      expect(validation.score).toBeGreaterThan(0);
      expect(analysis.score).toBeGreaterThan(0);
    });

    test('should scale with project complexity', async () => {
      const projectTypes = ['minimal', 'basic', 'enterprise'];
      const results = [];
      
      for (const type of projectTypes) {
        const projectDir = path.join(tempDir, type);
        await fs.mkdir(projectDir, { recursive: true });
        
        const start = Date.now();
        const context = new CSVLODContext();
        const result = await context.initialize(projectDir, type as any);
        const duration = Date.now() - start;
        
        results.push({
          type,
          duration,
          filesCount: result.filesCreated.length
        });
      }
      
      // Verify scaling characteristics
      expect(results[0].filesCount).toBeLessThan(results[2].filesCount); // minimal < enterprise
      expect(results[1].filesCount).toBeLessThan(results[2].filesCount); // basic < enterprise
      
      // Performance should still be reasonable even for enterprise
      results.forEach(result => {
        expect(result.duration).toBeLessThan(10000); // 10 seconds max
      });
    });
  });

  describe('Error Recovery Integration Tests', () => {
    test('should recover from partial failures gracefully', async () => {
      // Simulate partial initialization
      const context = new CSVLODContext();
      let initResult;
      
      try {
        initResult = await context.initialize(tempDir, 'basic');
      } catch (error) {
        // If initialization fails, should be handled gracefully
        expect(error).toBeDefined();
      }
      
      if (initResult) {
        // Attempt validation on potentially incomplete structure
        const validator = new CSVLODValidator();
        const validation = await validator.validate(tempDir, { strict: false });
        
        // Should provide helpful feedback even on incomplete structures
        expect(validation).toBeDefined();
        expect(validation.issues).toBeInstanceOf(Array);
        expect(validation.suggestions).toBeInstanceOf(Array);
        
        // Attempt to fix issues through generation
        const generator = new CSVLODGenerator();
        try {
          const fixes = await generator.generate('structure', tempDir);
          expect(fixes).toBeDefined();
        } catch (error) {
          // Generator should handle missing dependencies gracefully
          expect(error).toBeDefined();
        }
      }
    });

    test('should handle concurrent operations safely', async () => {
      const context = new CSVLODContext();
      
      // Initialize project first
      await context.initialize(tempDir, 'basic');
      
      // Run multiple operations concurrently
      const operations = [
        context.analyze(tempDir, { includeMetrics: false }),
        context.analyze(tempDir, { includeMetrics: true }),
        new CSVLODValidator().validate(tempDir, { strict: false }),
        new CSVLODValidator().validate(tempDir, { strict: true })
      ];
      
      const results = await Promise.allSettled(operations);
      
      // At least some operations should succeed
      const successful = results.filter(r => r.status === 'fulfilled');
      expect(successful.length).toBeGreaterThan(0);
      
      // Failed operations should have meaningful errors
      const failed = results.filter(r => r.status === 'rejected');
      failed.forEach(result => {
        if (result.status === 'rejected') {
          expect(result.reason).toBeDefined();
        }
      });
    });
  });

  describe('Real-World Scenario Tests', () => {
    test('should handle typical developer workflow', async () => {
      // Scenario: Developer initializes new project, adds features, validates compliance
      
      // Day 1: Project setup
      const context = new CSVLODContext();
      const initResult = await context.initialize(tempDir, 'basic');
      expect(initResult.filesCreated.length).toBeGreaterThan(0);
      
      // Day 2: Add new component
      const generator = new CSVLODGenerator();
      const newComponent = await generator.generate('prompt', tempDir, {
        framework: 'fastapi',
        language: 'python'
      });
      expect(newComponent.outputPath).toBeDefined();
      
      // Day 3: Team validation before merge
      const validator = new CSVLODValidator();
      const premergeValidation = await validator.validate(tempDir, { strict: true });
      expect(premergeValidation).toBeDefined();
      
      // Day 4: Performance analysis
      const analysis = await context.analyze(tempDir, { includeMetrics: true });
      expect(analysis.score).toBeGreaterThan(0);
      
      // Day 5: Team swarm coordination for new feature
      const coordinator = await createSwarmCoordinator(tempDir);
      const tasks = await coordinator.decomposeTask(
        'Add user authentication with proper testing',
        tempDir,
        ['standards', 'patterns']
      );
      expect(tasks.length).toBeGreaterThan(0);
    });

    test('should handle enterprise migration scenario', async () => {
      // Scenario: Enterprise team migrating existing project to CSVLOD-AI
      
      // Phase 1: Initial assessment
      const validator = new CSVLODValidator();
      const preAssessment = await validator.validate('.', { strict: false });
      expect(preAssessment).toBeDefined();
      
      // Phase 2: Gradual framework introduction
      const context = new CSVLODContext();
      const migration = await context.initialize(tempDir, 'enterprise');
      expect(migration.filesCreated.length).toBeGreaterThan(0);
      
      // Phase 3: Team training and tool adoption
      const generator = new CSVLODGenerator();
      const trainingMaterials = await generator.generate('context', tempDir, {
        framework: 'enterprise-migration',
        aiTools: true
      });
      expect(trainingMaterials.outputPath).toBeDefined();
      
      // Phase 4: Full workflow implementation
      const coordinator = await createSwarmCoordinator(tempDir);
      const migrationTasks = await coordinator.decomposeTask(
        'Complete enterprise framework adoption with compliance checks',
        tempDir,
        ['principles', 'standards', 'designs']
      );
      expect(migrationTasks.length).toBeGreaterThan(0);
      
      // Phase 5: Compliance validation
      const compliance = await validator.validate(tempDir, { strict: true });
      expect(compliance.issues).toBeInstanceOf(Array);
    });
  });
}); 