"use strict";
/**
 * Integration Tests for Generation Orchestrator
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const generation_orchestrator_1 = require("./generation-orchestrator");
const checkpoint_manager_1 = require("../utils/checkpoint-manager");
describe('GenerationOrchestrator', () => {
    const testOutputDir = path.join(__dirname, '../../test-output-orchestrator');
    let orchestrator;
    // Sample workflow for testing
    const sampleWorkflow = {
        workflow: {
            id: 'test-workflow',
            name: 'Test Workflow',
            version: '1.0.0',
            description: 'Test workflow for orchestrator tests',
        },
        stack: {
            api: {
                type: 'backend',
                technology: 'typescript/express',
                config: { port: 3000 },
            },
        },
        stages: {
            local: {
                infrastructure: {
                    databases: {
                        primary: 'postgresql://localhost:5432/test',
                    },
                    services: {},
                },
            },
        },
    };
    beforeEach(() => {
        // Clean up test directory
        if (fs.existsSync(testOutputDir)) {
            fs.rmSync(testOutputDir, { recursive: true, force: true });
        }
        fs.mkdirSync(testOutputDir, { recursive: true });
        orchestrator = new generation_orchestrator_1.GenerationOrchestrator();
    });
    afterEach(() => {
        // Clean up
        if (fs.existsSync(testOutputDir)) {
            fs.rmSync(testOutputDir, { recursive: true, force: true });
        }
    });
    describe('Successful Generation', () => {
        it('should generate code successfully', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true, // Use dry run to avoid actual file writing
                verbose: false,
            });
            expect(result.errors.length).toBe(0);
            expect(result.files.length).toBeGreaterThan(0);
        });
        it('should create checkpoints during generation', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.checkpoint).toBeDefined();
            expect(result.checkpoint?.stage).toBe(checkpoint_manager_1.GenerationStage.COMPLETE);
            expect(result.checkpoint?.percentage).toBe(100);
        });
        it('should track generated files', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.files.length).toBeGreaterThan(0);
            expect(result.written.length).toBeGreaterThan(0);
        });
        it('should cleanup checkpoints after success', async () => {
            const _result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: false, // Cleanup only happens when not in dry run
            });
            // After successful generation, checkpoints should be cleaned up
            const checkpointDir = path.join(testOutputDir, '.bangstack', 'checkpoints');
            if (fs.existsSync(checkpointDir)) {
                const files = fs.readdirSync(checkpointDir);
                // Should have at most 1 file (the COMPLETE checkpoint)
                expect(files.filter(f => f.endsWith('.json')).length).toBeLessThanOrEqual(1);
            }
        });
    });
    describe('Checkpoint System', () => {
        it('should create checkpoints at each stage', async () => {
            const _result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            const checkpoint = orchestrator.getCheckpointManager();
            expect(checkpoint).toBeDefined();
            const progress = checkpoint?.getProgress();
            expect(progress?.completedStages.length).toBeGreaterThan(0);
        });
        it('should allow disabling checkpoints', async () => {
            const _result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                noCheckpoint: true,
            });
            const checkpoint = orchestrator.getCheckpointManager();
            expect(checkpoint).toBeUndefined();
        });
        it('should indicate can resume after partial failure', async () => {
            // This would require simulating a failure mid-generation
            // For now, just test the structure
            const checkpoint = orchestrator.getCheckpointManager();
            if (checkpoint) {
                expect(checkpoint.canResume).toBeDefined();
            }
        });
    });
    describe('Error Handling', () => {
        it('should handle invalid workflow', async () => {
            const invalidWorkflow = {
                ...sampleWorkflow,
                stack: undefined,
            };
            const result = await orchestrator.generate(invalidWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.errors.length).toBeGreaterThan(0);
        });
        it('should aggregate errors', async () => {
            const errorAggregator = orchestrator.getErrorAggregator();
            expect(errorAggregator).toBeDefined();
        });
        it('should format errors with recovery strategies', async () => {
            const invalidWorkflow = {
                workflow: {
                    id: 'test',
                    name: 'Test',
                    version: '1.0.0',
                    description: 'Test invalid workflow',
                },
                stack: undefined,
                stages: {},
            };
            const result = await orchestrator.generate(invalidWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            if (result.errors.length > 0) {
                // Errors should be formatted strings
                expect(typeof result.errors[0]).toBe('string');
            }
        });
    });
    describe('Retry Logic', () => {
        it('should enable retry by default', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                retryTransient: true,
            });
            // Should complete without explicit retry configuration
            expect(result).toBeDefined();
        });
        it('should allow disabling retry', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                retryTransient: false,
            });
            expect(result).toBeDefined();
            // When retry is disabled, retries should be 0 or undefined
            expect(result.retries === 0 || result.retries === undefined).toBe(true);
        });
        it('should respect max retries configuration', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                maxRetries: 5,
            });
            expect(result).toBeDefined();
        });
        it('should track retry attempts', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // retries field should exist (0 if no retries needed)
            expect('retries' in result).toBe(true);
        });
    });
    describe('Rollback on Failure', () => {
        it('should rollback on failure by default', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                autoRollback: true,
            });
            // In a successful generation, rolledBack should be undefined or false
            // The field is only set to true when a rollback actually occurs
            expect(result.rolledBack === false || result.rolledBack === undefined).toBe(true);
        });
        it('should allow disabling auto-rollback', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                autoRollback: false,
            });
            expect(result).toBeDefined();
        });
    });
    describe('Resume Capability', () => {
        it('should support resume flag', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                resume: true,
            });
            // Should handle resume gracefully even if no checkpoint exists
            expect(result).toBeDefined();
        });
        it('should provide checkpoint information for resume', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            if (result.checkpoint) {
                expect(result.checkpoint.canResume).toBeDefined();
                expect(result.checkpoint.stage).toBeDefined();
                expect(result.checkpoint.percentage).toBeDefined();
            }
        });
    });
    describe('Validation Stage', () => {
        it('should validate workflow structure', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Valid workflow should pass validation
            expect(result.errors.length).toBe(0);
        });
        it('should fail on missing required fields', async () => {
            const invalidWorkflow = {
                workflow: {
                    id: 'test',
                    name: 'Test',
                    // Missing version
                },
                stack: {},
                stages: {},
            };
            const result = await orchestrator.generate(invalidWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.errors.length).toBeGreaterThan(0);
        });
    });
    describe('Analysis Stage', () => {
        it('should analyze workflow dependencies', async () => {
            const workflowWithDeps = {
                ...sampleWorkflow,
                stack: {
                    api: {
                        type: 'backend',
                        technology: 'typescript/express',
                        config: { port: 3000 },
                        dependsOn: ['database'],
                    },
                    database: {
                        type: 'database',
                        technology: 'postgresql/prisma',
                    },
                },
            };
            const result = await orchestrator.generate(workflowWithDeps, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Should handle dependencies correctly
            expect(result.errors.length).toBe(0);
        });
        it('should detect circular dependencies', async () => {
            const workflowWithCircular = {
                ...sampleWorkflow,
                stack: {
                    api: {
                        type: 'backend',
                        technology: 'typescript/express',
                        config: { port: 3000 },
                        dependsOn: ['worker'],
                    },
                    worker: {
                        type: 'backend',
                        technology: 'typescript/node',
                        dependsOn: ['api'],
                    },
                },
            };
            const result = await orchestrator.generate(workflowWithCircular, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Should detect circular dependency
            // Note: This depends on engine.analyze detecting cycles
            expect(result).toBeDefined();
        });
    });
    describe('Component Generation Stage', () => {
        it('should generate all stack components', async () => {
            const multiComponentWorkflow = {
                ...sampleWorkflow,
                stack: {
                    api: {
                        type: 'backend',
                        technology: 'typescript/express',
                        config: { port: 3000 },
                    },
                    worker: {
                        type: 'backend',
                        technology: 'typescript/node',
                    },
                },
            };
            const result = await orchestrator.generate(multiComponentWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.errors.length).toBe(0);
            expect(result.files.length).toBeGreaterThan(0);
        });
        it('should handle partial component generation', async () => {
            // This would require mocking component generation to fail
            // For now, test the structure
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.warnings).toBeDefined();
        });
    });
    describe('Configuration Stage', () => {
        it('should generate Docker configuration', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Check if Docker config files are generated
            const dockerFile = result.files.find(f => f.path.includes('docker-compose'));
            expect(dockerFile).toBeDefined();
        });
        it('should generate CI/CD configuration', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Check if CI/CD config files are generated
            const _ciFile = result.files.find(f => f.path.includes('.github'));
            // CI/CD generation might be optional
            expect(result).toBeDefined();
        });
    });
    describe('Finalization Stage', () => {
        it('should generate manifest', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            const manifestFile = result.files.find(f => f.path.includes('manifest.json'));
            expect(manifestFile).toBeDefined();
        });
        it('should mark generation as complete', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.checkpoint?.stage).toBe(checkpoint_manager_1.GenerationStage.COMPLETE);
        });
    });
    describe('Dry Run Mode', () => {
        it('should not write files in dry run', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.files.length).toBeGreaterThan(0);
            expect(result.written.length).toBeGreaterThan(0);
            // In dry run, files should not actually exist
            // (They're marked as written but not actually created)
        });
        it('should show what would be generated', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result.files.length).toBeGreaterThan(0);
            result.files.forEach(file => {
                expect(file.path).toBeDefined();
                expect(file.content).toBeDefined();
            });
        });
    });
    describe('Verbose Mode', () => {
        it('should provide detailed output in verbose mode', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                verbose: true,
            });
            // Verbose mode should complete successfully
            expect(result).toBeDefined();
        });
    });
    describe('Output Organization', () => {
        it('should organize files by component', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            const apiFiles = result.files.filter(f => f.path.includes('api'));
            expect(apiFiles.length).toBeGreaterThan(0);
        });
        it('should create proper directory structure', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Files should have proper paths
            result.files.forEach(file => {
                expect(file.path).toMatch(/[\\/]/); // Should contain path separators
            });
        });
    });
    describe('Extended Workflow Support', () => {
        it('should handle extended workflow schema', async () => {
            // Extended workflow test - skip for now as it requires full schema
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            expect(result).toBeDefined();
        });
    });
    describe('Error Recovery', () => {
        it('should provide recovery suggestions', async () => {
            const invalidWorkflow = {
                workflow: {
                    id: 'test',
                    name: 'Test',
                    version: '1.0.0',
                    description: 'Test invalid workflow',
                },
                stack: undefined,
                stages: {},
            };
            const result = await orchestrator.generate(invalidWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            if (result.errors.length > 0) {
                // Errors should contain recovery information
                const errorText = result.errors[0];
                expect(typeof errorText).toBe('string');
            }
        });
    });
    describe('Performance', () => {
        it('should complete generation in reasonable time', async () => {
            const startTime = Date.now();
            await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            const duration = Date.now() - startTime;
            // Should complete within 5 seconds for dry run
            expect(duration).toBeLessThan(5000);
        });
    });
    describe('Integration with CodeGenerator', () => {
        it('should delegate to CodeGenerator', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
            });
            // Should produce files from CodeGenerator
            expect(result.files.length).toBeGreaterThan(0);
        });
        it('should pass options to CodeGenerator', async () => {
            const result = await orchestrator.generate(sampleWorkflow, {
                outputDirectory: testOutputDir,
                dryRun: true,
                verbose: true,
            });
            expect(result).toBeDefined();
        });
    });
});
//# sourceMappingURL=generation-orchestrator.test.js.map