"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('Context Operations Integration Tests', () => {
    let dbManager;
    let tempDbPath;
    let db;
    let testSessionId;
    beforeEach(() => {
        tempDbPath = path.join(os.tmpdir(), `test-context-${Date.now()}.db`);
        dbManager = new database_1.DatabaseManager({
            filename: tempDbPath,
            maxSize: 10 * 1024 * 1024,
            walMode: true,
        });
        db = dbManager.getDatabase();
        // Create test session
        testSessionId = (0, uuid_1.v4)();
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(testSessionId, 'Test Session');
    });
    afterEach(() => {
        dbManager.close();
        try {
            fs.unlinkSync(tempDbPath);
            fs.unlinkSync(`${tempDbPath}-wal`);
            fs.unlinkSync(`${tempDbPath}-shm`);
        }
        catch (_e) {
            // Ignore
        }
    });
    describe('context_save', () => {
        it('should save a basic context item', () => {
            const result = db
                .prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)')
                .run((0, uuid_1.v4)(), testSessionId, 'test_key', 'test_value');
            expect(result.changes).toBe(1);
            const saved = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .get(testSessionId, 'test_key');
            expect(saved).toBeDefined();
            expect(saved.key).toBe('test_key');
            expect(saved.value).toBe('test_value');
        });
        it('should save context with category and priority', () => {
            const id = (0, uuid_1.v4)();
            db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run(id, testSessionId, 'task_item', 'Fix bug in auth', 'task', 'high');
            const saved = db.prepare('SELECT * FROM context_items WHERE id = ?').get(id);
            expect(saved.category).toBe('task');
            expect(saved.priority).toBe('high');
        });
        it('should update existing key in same session', () => {
            // Insert first
            db.prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, 'update_key', 'original_value');
            // Update using INSERT OR REPLACE
            db.prepare('INSERT OR REPLACE INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, 'update_key', 'updated_value');
            const items = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .all(testSessionId, 'update_key');
            expect(items).toHaveLength(1);
            expect(items[0].value).toBe('updated_value');
        });
        it('should handle large values', () => {
            const largeValue = 'x'.repeat(10000); // 10KB of data
            const result = db
                .prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)')
                .run((0, uuid_1.v4)(), testSessionId, 'large_key', largeValue);
            expect(result.changes).toBe(1);
            const saved = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .get(testSessionId, 'large_key');
            expect(saved.value).toBe(largeValue);
        });
        it('should handle special characters in values', () => {
            const specialValue = `Line 1\nLine 2\t"quoted"\n'single'\n\`backtick\``;
            db.prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, 'special_key', specialValue);
            const saved = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .get(testSessionId, 'special_key');
            expect(saved.value).toBe(specialValue);
        });
    });
    describe('context_get', () => {
        beforeEach(() => {
            // Add test data
            const items = [
                { key: 'item1', value: 'value1', category: 'task', priority: 'high' },
                { key: 'item2', value: 'value2', category: 'task', priority: 'normal' },
                { key: 'item3', value: 'value3', category: 'decision', priority: 'high' },
                { key: 'item4', value: 'value4', category: 'note', priority: 'low' },
            ];
            items.forEach(item => {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category, priority) VALUES (?, ?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, item.key, item.value, item.category, item.priority);
            });
        });
        it('should get item by key', () => {
            const item = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .get(testSessionId, 'item1');
            expect(item).toBeDefined();
            expect(item.value).toBe('value1');
            expect(item.category).toBe('task');
        });
        it('should get all items for session', () => {
            const items = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? ORDER BY key')
                .all(testSessionId);
            expect(items).toHaveLength(4);
            expect(items[0].key).toBe('item1');
            expect(items[3].key).toBe('item4');
        });
        it('should filter by category', () => {
            const tasks = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND category = ?')
                .all(testSessionId, 'task');
            expect(tasks).toHaveLength(2);
            expect(tasks.every((t) => t.category === 'task')).toBe(true);
        });
        it('should filter by priority', () => {
            const highPriority = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND priority = ?')
                .all(testSessionId, 'high');
            expect(highPriority).toHaveLength(2);
            expect(highPriority.every((t) => t.priority === 'high')).toBe(true);
        });
        it('should filter by category and priority', () => {
            const highTasks = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND category = ? AND priority = ?')
                .all(testSessionId, 'task', 'high');
            expect(highTasks).toHaveLength(1);
            expect(highTasks[0].key).toBe('item1');
        });
        it('should return empty array when no matches', () => {
            const items = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .all(testSessionId, 'nonexistent');
            expect(items).toHaveLength(0);
        });
        it('should get items from specific session', () => {
            // Create another session
            const otherSessionId = (0, uuid_1.v4)();
            db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(otherSessionId, 'Other Session');
            db.prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), otherSessionId, 'other_item', 'other_value');
            // Get from specific session
            const items = db
                .prepare('SELECT * FROM context_items WHERE session_id = ?')
                .all(otherSessionId);
            expect(items).toHaveLength(1);
            expect(items[0].key).toBe('other_item');
        });
    });
    describe('context_status', () => {
        it('should show status with no items', () => {
            const session = db.prepare('SELECT * FROM sessions WHERE id = ?').get(testSessionId);
            const itemCount = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ?')
                .get(testSessionId);
            const fileCount = db
                .prepare('SELECT COUNT(*) as count FROM file_cache WHERE session_id = ?')
                .get(testSessionId);
            expect(session).toBeDefined();
            expect(itemCount.count).toBe(0);
            expect(fileCount.count).toBe(0);
        });
        it('should show complete status information', () => {
            // Add some data
            for (let i = 0; i < 5; i++) {
                db.prepare('INSERT INTO context_items (id, session_id, key, value, category) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, `key${i}`, `value${i}`, i % 2 === 0 ? 'task' : 'note');
            }
            for (let i = 0; i < 3; i++) {
                db.prepare('INSERT INTO file_cache (id, session_id, file_path, content, hash) VALUES (?, ?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, `/file${i}.txt`, `content${i}`, `hash${i}`);
            }
            // Get status
            const itemCount = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ?')
                .get(testSessionId);
            const fileCount = db
                .prepare('SELECT COUNT(*) as count FROM file_cache WHERE session_id = ?')
                .get(testSessionId);
            const categoryBreakdown = db
                .prepare(`SELECT category, COUNT(*) as count 
         FROM context_items 
         WHERE session_id = ? 
         GROUP BY category`)
                .all(testSessionId);
            expect(itemCount.count).toBe(5);
            expect(fileCount.count).toBe(3);
            expect(categoryBreakdown).toHaveLength(2);
            expect(categoryBreakdown.find((c) => c.category === 'task')?.count).toBe(3);
            expect(categoryBreakdown.find((c) => c.category === 'note')?.count).toBe(2);
        });
        it('should calculate database size', () => {
            // Add substantial data
            const largeContent = 'x'.repeat(1000);
            for (let i = 0; i < 10; i++) {
                db.prepare('INSERT INTO context_items (id, session_id, key, value) VALUES (?, ?, ?, ?)').run((0, uuid_1.v4)(), testSessionId, `large${i}`, largeContent);
            }
            // Calculate approximate size
            const items = db
                .prepare('SELECT LENGTH(value) as size FROM context_items WHERE session_id = ?')
                .all(testSessionId);
            const totalSize = items.reduce((sum, item) => sum + item.size, 0);
            expect(totalSize).toBe(10000); // 10 items × 1000 chars
        });
    });
});
