"use strict";
/**
 * Tests for Checkpoint Manager
 */
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 checkpoint_manager_1 = require("./checkpoint-manager");
// Helper to ensure checkpoints have different timestamps
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
describe('CheckpointManager', () => {
    const testOutputDir = path.join(__dirname, '../../test-output');
    const checkpointDir = path.join(testOutputDir, '.bangstack', 'checkpoints');
    let manager;
    beforeEach(() => {
        // Clean up test directory
        if (fs.existsSync(testOutputDir)) {
            fs.rmSync(testOutputDir, { recursive: true, force: true });
        }
        fs.mkdirSync(testOutputDir, { recursive: true });
        manager = new checkpoint_manager_1.CheckpointManager(testOutputDir);
        manager.initialize();
    });
    afterEach(() => {
        // Clean up
        if (fs.existsSync(testOutputDir)) {
            fs.rmSync(testOutputDir, { recursive: true, force: true });
        }
    });
    describe('Initialization', () => {
        it('should create checkpoint directory on initialize', () => {
            expect(fs.existsSync(checkpointDir)).toBe(true);
        });
        it('should load existing checkpoints', () => {
            // Create a checkpoint
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            expect(id).toBeDefined();
            // Create new manager instance to test loading
            const newManager = new checkpoint_manager_1.CheckpointManager(testOutputDir);
            newManager.initialize();
            const progress = newManager.getProgress();
            expect(progress.stage).toBe(checkpoint_manager_1.GenerationStage.VALIDATION);
        });
    });
    describe('Checkpoint Creation', () => {
        it('should create checkpoint with unique ID', () => {
            const id1 = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            const id2 = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            expect(id1).toBeDefined();
            expect(id2).toBeDefined();
            expect(id1).not.toBe(id2);
        });
        it('should create checkpoint file on disk', () => {
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            const checkpointPath = path.join(checkpointDir, `${id}.json`);
            expect(fs.existsSync(checkpointPath)).toBe(true);
        });
        it('should include metadata in checkpoint', () => {
            const metadata = { testKey: 'testValue', count: 42 };
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION, 'api', metadata);
            const checkpointPath = path.join(checkpointDir, `${id}.json`);
            const content = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));
            expect(content.metadata).toEqual(metadata);
            expect(content.component).toBe('api');
        });
        it('should track checkpoint stages in order', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            const progress = manager.getProgress();
            expect(progress.completedStages).toEqual([
                checkpoint_manager_1.GenerationStage.VALIDATION,
                checkpoint_manager_1.GenerationStage.ANALYSIS,
                checkpoint_manager_1.GenerationStage.INFRASTRUCTURE,
            ]);
        });
    });
    describe('File Tracking', () => {
        it('should record created files', () => {
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            manager.recordFileCreated('/output/src/index.ts');
            manager.recordFileCreated('/output/package.json');
            const checkpointPath = path.join(checkpointDir, `${id}.json`);
            const content = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));
            expect(content.filesCreated).toContain('/output/src/index.ts');
            expect(content.filesCreated).toContain('/output/package.json');
        });
        it('should record modified files with backups', () => {
            // Create a test file to modify
            const testFile = path.join(testOutputDir, 'test.txt');
            fs.writeFileSync(testFile, 'original content');
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.CONFIGURATION);
            manager.recordFileModified(testFile);
            const checkpointPath = path.join(checkpointDir, `${id}.json`);
            const content = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));
            expect(content.filesModified.length).toBe(1);
            expect(content.filesModified[0].path).toBe(testFile);
            expect(content.filesModified[0].backup).toContain('backups');
            // Verify backup was created
            expect(fs.existsSync(content.filesModified[0].backup)).toBe(true);
        });
        it('should record created directories', () => {
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            manager.recordDirectoryCreated('/output/src');
            manager.recordDirectoryCreated('/output/tests');
            const checkpointPath = path.join(checkpointDir, `${id}.json`);
            const content = JSON.parse(fs.readFileSync(checkpointPath, 'utf-8'));
            expect(content.directoriesCreated).toContain('/output/src');
            expect(content.directoriesCreated).toContain('/output/tests');
        });
    });
    describe('Progress Tracking', () => {
        it('should calculate progress percentage', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            let progress = manager.getProgress();
            expect(progress.percentage).toBeGreaterThan(0);
            expect(progress.percentage).toBeLessThan(100);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPLETE);
            progress = manager.getProgress();
            expect(progress.percentage).toBe(100);
        });
        it('should return current stage', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            const progress = manager.getProgress();
            expect(progress.stage).toBe(checkpoint_manager_1.GenerationStage.ANALYSIS);
        });
        it('should return current component if set', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION, 'api');
            const progress = manager.getProgress();
            expect(progress.currentComponent).toBe('api');
        });
    });
    describe('Resume Capability', () => {
        it('should indicate can resume when incomplete', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            expect(manager.canResume()).toBe(true);
        });
        it('should indicate cannot resume when complete', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPLETE);
            expect(manager.canResume()).toBe(false);
        });
        it('should provide resume point', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION, 'api');
            const resumePoint = manager.getResumePoint();
            expect(resumePoint).toBeDefined();
            expect(resumePoint?.stage).toBe(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION);
            expect(resumePoint?.component).toBe('api');
        });
        it('should return null resume point when complete', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPLETE);
            const resumePoint = manager.getResumePoint();
            expect(resumePoint).toBeNull();
        });
    });
    describe('Rollback', () => {
        it('should remove files created after checkpoint', async () => {
            // Create checkpoint
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            // Create some files
            const file1 = path.join(testOutputDir, 'file1.txt');
            const file2 = path.join(testOutputDir, 'file2.txt');
            fs.writeFileSync(file1, 'content1');
            fs.writeFileSync(file2, 'content2');
            // Small delay to ensure different timestamp
            await sleep(2);
            // Record in next checkpoint
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION);
            manager.recordFileCreated(file1);
            manager.recordFileCreated(file2);
            // Rollback to first checkpoint
            const result = manager.rollback(id);
            expect(result.success).toBe(true);
            expect(fs.existsSync(file1)).toBe(false);
            expect(fs.existsSync(file2)).toBe(false);
            expect(result.filesRemoved).toContain(file1);
            expect(result.filesRemoved).toContain(file2);
        });
        it('should restore modified files from backup', async () => {
            // Create checkpoint
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            // Create and modify a file
            const testFile = path.join(testOutputDir, 'test.txt');
            fs.writeFileSync(testFile, 'original content');
            // Small delay to ensure different timestamp
            await sleep(2);
            // Create next checkpoint and record modification
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION);
            manager.recordFileModified(testFile);
            // Modify the file again
            fs.writeFileSync(testFile, 'modified content');
            // Rollback to first checkpoint
            const result = manager.rollback(id);
            expect(result.success).toBe(true);
            expect(fs.readFileSync(testFile, 'utf-8')).toBe('original content');
            expect(result.filesRestored).toContain(testFile);
        });
        it('should remove empty directories', async () => {
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            // Create directory
            const testDir = path.join(testOutputDir, 'testdir');
            fs.mkdirSync(testDir);
            // Small delay to ensure different timestamp
            await sleep(2);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION);
            manager.recordDirectoryCreated(testDir);
            // Rollback
            const result = manager.rollback(id);
            expect(result.success).toBe(true);
            expect(fs.existsSync(testDir)).toBe(false);
            expect(result.directoriesRemoved).toContain(testDir);
        });
        it('should not remove non-empty directories', async () => {
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            // Create directory with file
            const testDir = path.join(testOutputDir, 'testdir');
            fs.mkdirSync(testDir);
            fs.writeFileSync(path.join(testDir, 'file.txt'), 'content');
            // Small delay to ensure different timestamp
            await sleep(2);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION);
            manager.recordDirectoryCreated(testDir);
            // Rollback
            const result = manager.rollback(id);
            expect(result.success).toBe(true);
            expect(fs.existsSync(testDir)).toBe(true); // Directory still exists
            expect(result.directoriesRemoved || []).not.toContain(testDir);
        });
        it('should rollback to last checkpoint by default', async () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            await sleep(2);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            await sleep(2);
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            const file = path.join(testOutputDir, 'file.txt');
            fs.writeFileSync(file, 'content');
            // Small delay to ensure different timestamp
            await sleep(2);
            // Create another checkpoint and record the file
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPONENT_GENERATION);
            manager.recordFileCreated(file);
            // Rollback to previous checkpoint (INFRASTRUCTURE)
            const result = manager.rollback(id);
            expect(result.success).toBe(true);
            expect(fs.existsSync(file)).toBe(false);
        });
        it('should handle rollback with no checkpoint', () => {
            const result = manager.rollback();
            expect(result.success).toBe(false);
            expect(result.message).toContain('No checkpoint');
        });
        it('should handle rollback errors gracefully', () => {
            const id = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            // Record a file that doesn't exist
            manager.recordFileCreated('/nonexistent/file.txt');
            const result = manager.rollback(id);
            // Should still succeed even though file doesn't exist
            expect(result.success).toBe(true);
        });
    });
    describe('Cleanup', () => {
        it('should keep complete checkpoint and remove others', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPLETE);
            manager.cleanup();
            const files = fs.readdirSync(checkpointDir);
            const checkpointFiles = files.filter(f => f.endsWith('.json'));
            expect(checkpointFiles.length).toBe(1);
        });
        it('should remove backup directory', () => {
            // Create a file and record modification to create backup
            const testFile = path.join(testOutputDir, 'test.txt');
            fs.writeFileSync(testFile, 'content');
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            manager.recordFileModified(testFile);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPLETE);
            const backupDir = path.join(checkpointDir, 'backups');
            expect(fs.existsSync(backupDir)).toBe(true);
            manager.cleanup();
            expect(fs.existsSync(backupDir)).toBe(false);
        });
    });
    describe('Summary Generation', () => {
        it('should generate summary with no checkpoints', () => {
            const summary = manager.getSummary();
            expect(summary).toContain('No checkpoints found');
        });
        it('should generate summary with checkpoints', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            const summary = manager.getSummary();
            expect(summary).toContain('Generation Progress');
            expect(summary).toContain('Stage:');
            expect(summary).toContain('Progress:');
            expect(summary).toContain('Checkpoints:');
            expect(summary).toContain(checkpoint_manager_1.GenerationStage.VALIDATION);
            expect(summary).toContain(checkpoint_manager_1.GenerationStage.ANALYSIS);
        });
        it('should show resume suggestion when can resume', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            const summary = manager.getSummary();
            expect(summary).toContain('Can resume');
            expect(summary).toContain('--resume');
        });
        it('should show completion when complete', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.COMPLETE);
            const summary = manager.getSummary();
            expect(summary).toContain('✓');
        });
    });
    describe('Edge Cases', () => {
        it('should handle recording when no current checkpoint', () => {
            // Should not throw
            expect(() => {
                manager.recordFileCreated('/some/file.txt');
                manager.recordDirectoryCreated('/some/dir');
            }).not.toThrow();
        });
        it('should handle recording modification of non-existent file', () => {
            manager.createCheckpoint(checkpoint_manager_1.GenerationStage.INFRASTRUCTURE);
            // Should not throw
            expect(() => {
                manager.recordFileModified('/nonexistent/file.txt');
            }).not.toThrow();
        });
        it('should handle multiple rollbacks', () => {
            const id1 = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.VALIDATION);
            const id2 = manager.createCheckpoint(checkpoint_manager_1.GenerationStage.ANALYSIS);
            const file = path.join(testOutputDir, 'file.txt');
            fs.writeFileSync(file, 'content');
            manager.recordFileCreated(file);
            // First rollback
            let result = manager.rollback(id2);
            expect(result.success).toBe(true);
            // Second rollback to earlier checkpoint
            result = manager.rollback(id1);
            expect(result.success).toBe(true);
        });
    });
});
//# sourceMappingURL=checkpoint-manager.test.js.map