"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 globals_1 = require("@jest/globals");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const os = __importStar(require("os"));
const database_js_1 = require("../../utils/database.js");
(0, globals_1.describe)('Resource Cleanup Tests', () => {
    let tempDir;
    (0, globals_1.beforeEach)(() => {
        tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mcp-test-'));
    });
    (0, globals_1.afterEach)(() => {
        fs.rmSync(tempDir, { recursive: true, force: true });
    });
    (0, globals_1.it)('should properly close database connections', () => {
        const tempDbPath = path.join(tempDir, 'test.db');
        const dbManager = new database_js_1.DatabaseManager({ filename: tempDbPath });
        const db = dbManager.getDatabase();
        // Verify database is open
        (0, globals_1.expect)(() => {
            db.prepare('SELECT 1').get();
        }).not.toThrow();
        // Close the database
        dbManager.close();
        // Verify database is closed
        (0, globals_1.expect)(() => {
            db.prepare('SELECT 1').get();
        }).toThrow('The database connection is not open');
    });
    (0, globals_1.it)('should release file locks after closing', () => {
        const tempDbPath = path.join(tempDir, 'test.db');
        const dbManager = new database_js_1.DatabaseManager({ filename: tempDbPath });
        // Database should be created
        (0, globals_1.expect)(fs.existsSync(tempDbPath)).toBe(true);
        // Close the database
        dbManager.close();
        // Should be able to delete the file (no locks)
        (0, globals_1.expect)(() => {
            fs.unlinkSync(tempDbPath);
        }).not.toThrow();
    });
    (0, globals_1.it)('should handle errors during initialization gracefully', () => {
        // Try to create database in non-existent directory
        const invalidPath = path.join(tempDir, 'non-existent', 'test.db');
        (0, globals_1.expect)(() => {
            new database_js_1.DatabaseManager({ filename: invalidPath });
        }).toThrow();
    });
    (0, globals_1.it)('should clean up WAL files on close', () => {
        const tempDbPath = path.join(tempDir, 'test.db');
        const dbManager = new database_js_1.DatabaseManager({ filename: tempDbPath });
        const db = dbManager.getDatabase();
        // Perform some operations to ensure WAL files are created
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run('test', 'Test');
        // WAL files should exist
        (0, globals_1.expect)(fs.existsSync(tempDbPath + '-wal')).toBe(true);
        (0, globals_1.expect)(fs.existsSync(tempDbPath + '-shm')).toBe(true);
        // Close database
        dbManager.close();
        // WAL files should be cleaned up
        // Note: They might still exist but should be minimal size
        if (fs.existsSync(tempDbPath + '-wal')) {
            const walSize = fs.statSync(tempDbPath + '-wal').size;
            (0, globals_1.expect)(walSize).toBe(0);
        }
    });
    (0, globals_1.it)('should handle multiple close calls safely', () => {
        const tempDbPath = path.join(tempDir, 'test.db');
        const dbManager = new database_js_1.DatabaseManager({ filename: tempDbPath });
        // First close
        (0, globals_1.expect)(() => {
            dbManager.close();
        }).not.toThrow();
        // Second close should not throw
        (0, globals_1.expect)(() => {
            dbManager.close();
        }).not.toThrow();
    });
    (0, globals_1.it)('should release memory for large operations', () => {
        const tempDbPath = path.join(tempDir, 'test.db');
        const dbManager = new database_js_1.DatabaseManager({ filename: tempDbPath });
        const db = dbManager.getDatabase();
        // Create session
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run('test', 'Test');
        // Insert many items
        const stmt = db.prepare(`
      INSERT INTO context_items (id, session_id, key, value, category, priority)
      VALUES (?, ?, ?, ?, ?, ?)
    `);
        const largeValue = 'x'.repeat(1000); // 1KB per value
        // Use transaction for better performance
        const insertMany = db.transaction((count) => {
            for (let i = 0; i < count; i++) {
                stmt.run(`item-${i}`, 'test', `key-${i}`, largeValue, 'test', 'normal');
            }
        });
        // Insert 1000 items (1MB of data)
        insertMany(1000);
        // Verify data was inserted
        const count = db.prepare('SELECT COUNT(*) as count FROM context_items').get();
        (0, globals_1.expect)(count.count).toBe(1000);
        // Close and cleanup
        dbManager.close();
        // Memory should be released (hard to test directly, but no errors should occur)
    });
    (0, globals_1.it)('should handle database file corruption gracefully', () => {
        const tempDbPath = path.join(tempDir, 'corrupt.db');
        // Create a corrupted database file
        fs.writeFileSync(tempDbPath, 'This is not a valid SQLite database');
        // Should throw when trying to open corrupted database
        (0, globals_1.expect)(() => {
            new database_js_1.DatabaseManager({ filename: tempDbPath });
        }).toThrow(/not a database|malformed/);
    });
});
