"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('Session Management Integration Tests', () => {
    let dbManager;
    let tempDbPath;
    let db;
    beforeEach(() => {
        tempDbPath = path.join(os.tmpdir(), `test-session-${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('Session lifecycle', () => {
        it('should create a new session', () => {
            const sessionId = (0, uuid_1.v4)();
            const result = db
                .prepare('INSERT INTO sessions (id, name, description, branch) VALUES (?, ?, ?, ?)')
                .run(sessionId, 'Test Session', 'Test Description', 'main');
            expect(result.changes).toBe(1);
            const session = db.prepare('SELECT * FROM sessions WHERE id = ?').get(sessionId);
            expect(session).toBeDefined();
            expect(session.name).toBe('Test Session');
            expect(session.description).toBe('Test Description');
            expect(session.branch).toBe('main');
        });
        it('should list sessions in order', () => {
            // Create multiple sessions
            const sessions = [
                { id: (0, uuid_1.v4)(), name: 'Session 1' },
                { id: (0, uuid_1.v4)(), name: 'Session 2' },
                { id: (0, uuid_1.v4)(), name: 'Session 3' },
            ];
            sessions.forEach((s, index) => {
                // Add delay to ensure different timestamps
                const date = new Date();
                date.setSeconds(date.getSeconds() - (sessions.length - index));
                db.prepare('INSERT INTO sessions (id, name, created_at) VALUES (?, ?, ?)').run(s.id, s.name, date.toISOString());
            });
            const results = db
                .prepare('SELECT * FROM sessions ORDER BY created_at DESC LIMIT 10')
                .all();
            expect(results).toHaveLength(3);
            expect(results[0].name).toBe('Session 3');
            expect(results[2].name).toBe('Session 1');
        });
        it('should copy context when continuing from previous session', () => {
            // Create source session
            const sourceSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sourceSessionId, 'Source Session');
            // Add context items
            const items = [
                { key: 'key1', value: 'value1', category: 'task', priority: 'high' },
                { key: 'key2', value: 'value2', category: 'decision', priority: 'normal' },
            ];
            items.forEach(item => {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), sourceSessionId, item.key, item.value, item.category, item.priority);
            });
            // Create new session and copy items
            const newSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(newSessionId, 'New Session');
            dbManager.transaction(() => {
                const sourceItems = db
                    .prepare('SELECT * FROM context_items WHERE session_id = ?')
                    .all(sourceSessionId);
                sourceItems.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 items were copied
            const copiedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? ORDER BY key')
                .all(newSessionId);
            expect(copiedItems).toHaveLength(2);
            expect(copiedItems[0].key).toBe('key1');
            expect(copiedItems[0].value).toBe('value1');
            expect(copiedItems[1].key).toBe('key2');
            expect(copiedItems[1].value).toBe('value2');
        });
    });
    describe('Context storage', () => {
        it('should save and retrieve context items', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            // Save context item
            const itemId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run(itemId, sessionId, 'test_key', 'test_value', 'task', 'high');
            // Retrieve item
            const item = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .get(sessionId, 'test_key');
            expect(item).toBeDefined();
            expect(item.value).toBe('test_value');
            expect(item.category).toBe('task');
            expect(item.priority).toBe('high');
        });
        it('should handle unique key constraint per session', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            // Insert first item
            db.prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, 'unique_key', 'value1');
            // Try to insert duplicate key - should replace
            db.prepare('INSERT OR REPLACE INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, 'unique_key', 'value2');
            const items = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .all(sessionId, 'unique_key');
            expect(items).toHaveLength(1);
            expect(items[0].value).toBe('value2');
        });
        it('should filter by category and priority', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            // Insert items with different categories and priorities
            const items = [
                { key: 'task1', category: 'task', priority: 'high' },
                { key: 'task2', category: 'task', priority: 'low' },
                { key: 'decision1', category: 'decision', priority: 'high' },
                { key: 'note1', category: 'note', priority: 'normal' },
            ];
            items.forEach(item => {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, item.key, 'value', item.category, item.priority);
            });
            // Filter by category
            const tasks = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND category = ?')
                .all(sessionId, 'task');
            expect(tasks).toHaveLength(2);
            // Filter by priority
            const highPriority = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND priority = ?')
                .all(sessionId, 'high');
            expect(highPriority).toHaveLength(2);
            expect(highPriority.map((i) => i.key).sort()).toEqual(['decision1', 'task1']);
        });
    });
    describe('File caching', () => {
        it('should cache file content with hash', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            const content = 'This is file content';
            const hash = require('crypto').createHash('sha256').update(content).digest('hex');
            db.prepare('INSERT INTO file_cache (id, session_id, file_path, content, hash) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, '/test/file.txt', content, hash);
            const cached = db
                .prepare('SELECT * FROM file_cache WHERE session_id = ? AND file_path = ?')
                .get(sessionId, '/test/file.txt');
            expect(cached).toBeDefined();
            expect(cached.content).toBe(content);
            expect(cached.hash).toBe(hash);
        });
        it('should detect file changes', () => {
            const sessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(sessionId, 'Test Session');
            const originalContent = 'Original content';
            const originalHash = require('crypto')
                .createHash('sha256')
                .update(originalContent)
                .digest('hex');
            db.prepare('INSERT INTO file_cache (id, session_id, file_path, content, hash) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), sessionId, '/test/file.txt', originalContent, originalHash);
            const newContent = 'Modified content';
            const newHash = require('crypto').createHash('sha256').update(newContent).digest('hex');
            const cached = db
                .prepare('SELECT * FROM file_cache WHERE session_id = ? AND file_path = ?')
                .get(sessionId, '/test/file.txt');
            expect(cached.hash).not.toBe(newHash);
            expect(originalHash).not.toBe(newHash);
        });
    });
});
