"use strict";
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 database_1 = require("../../utils/database");
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const uuid_1 = require("uuid");
describe('Checkpoint Integration Tests', () => {
    let dbManager;
    let tempDbPath;
    let db;
    beforeEach(() => {
        tempDbPath = path.join(os.tmpdir(), `test-checkpoint-${Date.now()}.db`);
        dbManager = new database_1.DatabaseManager({
            filename: tempDbPath,
            maxSize: 10 * 1024 * 1024,
            walMode: true,
        });
        db = dbManager.getDatabase();
    });
    afterEach(() => {
        dbManager.close();
        try {
            fs.unlinkSync(tempDbPath);
            fs.unlinkSync(`${tempDbPath}-wal`);
            fs.unlinkSync(`${tempDbPath}-shm`);
        }
        catch (_e) {
            // Ignore
        }
    });
    describe('Checkpoint creation', () => {
        it('should create a checkpoint with all context items', () => {
            // Setup session with context
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            // Add context items
            const contextItems = [];
            for (let i = 0; i < 5; i++) {
                const itemId = (0, uuid_1.v4)();
                contextItems.push(itemId);
                db.prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run(itemId, sessionId, `key${i}`, `value${i}`);
            }
            // Create checkpoint
            const checkpointId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO checkpoints (id, session_id, name, description) VALUES (?, ?, ?, ?)').run(checkpointId, sessionId, 'Test Checkpoint', 'Test Description');
            // Link context items to checkpoint
            contextItems.forEach(itemId => {
                db.prepare('INSERT INTO checkpoint_items (id, checkpoint_id, context_item_id) VALUES (?, ?, ?)').run((0, uuid_1.v4)(), checkpointId, itemId);
            });
            // Verify checkpoint was created
            const checkpoint = db
                .prepare('SELECT * FROM checkpoints WHERE id = ?')
                .get(checkpointId);
            expect(checkpoint).toBeDefined();
            expect(checkpoint.name).toBe('Test Checkpoint');
            // Verify all items are linked
            const linkedItems = db
                .prepare('SELECT COUNT(*) as count FROM checkpoint_items WHERE checkpoint_id = ?')
                .get(checkpointId);
            expect(linkedItems.count).toBe(5);
        });
        it('should include file cache in checkpoint', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            // Add file cache entries
            const fileIds = [];
            for (let i = 0; i < 3; i++) {
                const fileId = (0, uuid_1.v4)();
                fileIds.push(fileId);
                db.prepare('INSERT INTO file_cache (id, session_id, file_path, content, hash) VALUES (?, ?, ?, ?, ?)').run(fileId, sessionId, `/file${i}.txt`, `content${i}`, `hash${i}`);
            }
            // Create checkpoint
            const checkpointId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO checkpoints (id, session_id, name) VALUES (?, ?, ?)').run(checkpointId, sessionId, 'File Checkpoint');
            // Link files to checkpoint
            fileIds.forEach(fileId => {
                db.prepare('INSERT INTO checkpoint_files (id, checkpoint_id, file_cache_id) VALUES (?, ?, ?)').run((0, uuid_1.v4)(), checkpointId, fileId);
            });
            // Verify files are linked
            const linkedFiles = db
                .prepare('SELECT COUNT(*) as count FROM checkpoint_files WHERE checkpoint_id = ?')
                .get(checkpointId);
            expect(linkedFiles.count).toBe(3);
        });
        it('should capture git status in checkpoint', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            const gitStatus = JSON.stringify({
                modified: ['file1.ts'],
                created: ['file2.ts'],
                staged: ['file1.ts'],
            });
            const checkpointId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO checkpoints (id, session_id, name, git_status, git_branch) VALUES (?, ?, ?, ?, ?)').run(checkpointId, sessionId, 'Git Checkpoint', gitStatus, 'feature/test');
            const checkpoint = db
                .prepare('SELECT * FROM checkpoints WHERE id = ?')
                .get(checkpointId);
            expect(checkpoint.git_status).toBe(gitStatus);
            expect(checkpoint.git_branch).toBe('feature/test');
        });
    });
    describe('Checkpoint restoration', () => {
        it('should restore all context items from checkpoint', () => {
            // Create original session
            const originalSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(originalSessionId, 'Original');
            // Add context items
            const originalItems = [];
            for (let i = 0; i < 3; i++) {
                const itemId = (0, uuid_1.v4)();
                originalItems.push({
                    id: itemId,
                    key: `key${i}`,
                    value: `value${i}`,
                    category: 'task',
                    priority: 'high',
                });
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run(itemId, originalSessionId, `key${i}`, `value${i}`, 'task', 'high');
            }
            // Create checkpoint
            const checkpointId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO checkpoints (id, session_id, name) VALUES (?, ?, ?)').run(checkpointId, originalSessionId, 'Restore Test');
            // Link items to checkpoint
            originalItems.forEach(item => {
                db.prepare('INSERT INTO checkpoint_items (id, checkpoint_id, context_item_id) VALUES (?, ?, ?)').run((0, uuid_1.v4)(), checkpointId, item.id);
            });
            // Create new session and restore
            const newSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(newSessionId, 'Restored');
            // Restore items
            const itemsToRestore = db
                .prepare(`
        SELECT ci.* FROM context_items ci
        JOIN checkpoint_items cpi ON ci.id = cpi.context_item_id
        WHERE cpi.checkpoint_id = ?
      `)
                .all(checkpointId);
            itemsToRestore.forEach((item) => {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), newSessionId, item.key, item.value, item.category, item.priority);
            });
            // Verify restoration
            const restoredItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? ORDER BY key')
                .all(newSessionId);
            expect(restoredItems).toHaveLength(3);
            expect(restoredItems[0].key).toBe('key0');
            expect(restoredItems[0].value).toBe('value0');
            expect(restoredItems[0].category).toBe('task');
            expect(restoredItems[0].priority).toBe('high');
        });
        it('should restore file cache from checkpoint', () => {
            // Create original session with files
            const originalSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(originalSessionId, 'Original');
            // Add files
            const fileId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO file_cache (id, session_id, file_path, content, hash) VALUES (?, ?, ?, ?, ?)').run(fileId, originalSessionId, '/test/file.txt', 'file content', 'file hash');
            // Create checkpoint
            const checkpointId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO checkpoints (id, session_id, name) VALUES (?, ?, ?)').run(checkpointId, originalSessionId, 'File Restore Test');
            db.prepare('INSERT INTO checkpoint_files (id, checkpoint_id, file_cache_id) VALUES (?, ?, ?)').run((0, uuid_1.v4)(), checkpointId, fileId);
            // Restore to new session
            const newSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(newSessionId, 'Restored');
            const filesToRestore = db
                .prepare(`
        SELECT fc.* FROM file_cache fc
        JOIN checkpoint_files cpf ON fc.id = cpf.file_cache_id
        WHERE cpf.checkpoint_id = ?
      `)
                .all(checkpointId);
            filesToRestore.forEach((file) => {
                db.prepare('INSERT INTO file_cache (id, session_id, file_path, content, hash) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), newSessionId, file.file_path, file.content, file.hash);
            });
            // Verify restoration
            const restoredFile = db
                .prepare('SELECT * FROM file_cache WHERE session_id = ? AND file_path = ?')
                .get(newSessionId, '/test/file.txt');
            expect(restoredFile).toBeDefined();
            expect(restoredFile.content).toBe('file content');
            expect(restoredFile.hash).toBe('file hash');
        });
    });
    describe('Checkpoint management', () => {
        it('should list checkpoints for a session', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            // Create multiple checkpoints
            const checkpoints = [];
            for (let i = 0; i < 3; i++) {
                const checkpointId = (0, uuid_1.v4)();
                checkpoints.push({ id: checkpointId, name: `Checkpoint ${i}` });
                const date = new Date();
                date.setMinutes(date.getMinutes() - (3 - i)); // Different timestamps
                db.prepare('INSERT INTO checkpoints (id, session_id, name, created_at) VALUES (?, ?, ?, ?)').run(checkpointId, sessionId, `Checkpoint ${i}`, date.toISOString());
            }
            // List checkpoints
            const list = db
                .prepare('SELECT * FROM checkpoints WHERE session_id = ? ORDER BY created_at DESC')
                .all(sessionId);
            expect(list).toHaveLength(3);
            expect(list[0].name).toBe('Checkpoint 2'); // Most recent
            expect(list[2].name).toBe('Checkpoint 0'); // Oldest
        });
        it('should find checkpoint by name', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            const checkpointId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO checkpoints (id, session_id, name) VALUES (?, ?, ?)').run(checkpointId, sessionId, 'Named Checkpoint');
            const found = db
                .prepare('SELECT * FROM checkpoints WHERE session_id = ? AND name = ?')
                .get(sessionId, 'Named Checkpoint');
            expect(found).toBeDefined();
            expect(found.id).toBe(checkpointId);
        });
    });
});
