"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 database_1 = require("../../utils/database");
const ContextRepository_1 = require("../../repositories/ContextRepository");
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
const uuid_1 = require("uuid");
const validation_1 = require("../../utils/validation");
(0, globals_1.describe)('Context Reassign Channel Handler Integration Tests', () => {
    let dbManager;
    let tempDbPath;
    let db;
    let _contextRepo;
    let testSessionId;
    let secondSessionId;
    (0, globals_1.beforeEach)(() => {
        tempDbPath = path.join(os.tmpdir(), `test-context-reassign-channel-${Date.now()}.db`);
        dbManager = new database_1.DatabaseManager({
            filename: tempDbPath,
            maxSize: 10 * 1024 * 1024,
            walMode: true,
        });
        db = dbManager.getDatabase();
        _contextRepo = new ContextRepository_1.ContextRepository(dbManager);
        // Create test sessions
        testSessionId = (0, uuid_1.v4)();
        secondSessionId = (0, uuid_1.v4)();
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(testSessionId, 'Test Session');
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(secondSessionId, 'Second Session');
    });
    (0, globals_1.afterEach)(() => {
        dbManager.close();
        try {
            fs.unlinkSync(tempDbPath);
            fs.unlinkSync(`${tempDbPath}-wal`);
            fs.unlinkSync(`${tempDbPath}-shm`);
        }
        catch (_e) {
            // Ignore
        }
    });
    function createTestData() {
        const items = [
            // Main channel items
            {
                key: 'config.database.url',
                value: 'postgresql://localhost:5432/myapp',
                category: 'config',
                priority: 'high',
                channel: 'main',
            },
            {
                key: 'config.cache.ttl',
                value: '3600',
                category: 'config',
                priority: 'normal',
                channel: 'main',
            },
            {
                key: 'task.deploy.status',
                value: 'completed',
                category: 'task',
                priority: 'high',
                channel: 'main',
            },
            // Feature branch items
            {
                key: 'feature.auth.enabled',
                value: 'true',
                category: 'config',
                priority: 'high',
                channel: 'feature/auth',
            },
            {
                key: 'feature.auth.provider',
                value: 'oauth2',
                category: 'config',
                priority: 'normal',
                channel: 'feature/auth',
            },
            {
                key: 'task.auth.implement',
                value: 'in_progress',
                category: 'task',
                priority: 'high',
                channel: 'feature/auth',
            },
            // Development channel items
            {
                key: 'dev.debug.enabled',
                value: 'true',
                category: 'config',
                priority: 'low',
                channel: 'development',
            },
            {
                key: 'dev.log.level',
                value: 'debug',
                category: 'config',
                priority: 'low',
                channel: 'development',
            },
            // Private item
            {
                key: 'secret.api.key',
                value: 'sk-1234567890',
                category: 'config',
                priority: 'high',
                channel: 'secure',
                is_private: 1,
            },
            // Item from another session
            {
                key: 'other.session.item',
                value: 'Not accessible',
                category: 'note',
                priority: 'normal',
                channel: 'main',
                session_id: secondSessionId,
            },
        ];
        const stmt = db.prepare(`
      INSERT INTO context_items (
        id, session_id, key, value, category, priority, channel, is_private
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
    `);
        items.forEach(item => {
            stmt.run((0, uuid_1.v4)(), item.session_id || testSessionId, item.key, item.value, item.category, item.priority, item.channel, item.is_private || 0);
        });
    }
    (0, globals_1.describe)('Reassign by Specific Keys', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should reassign specific keys to a new channel', () => {
            const keysToMove = ['config.database.url', 'config.cache.ttl'];
            const newChannel = 'production';
            // Simulate handler logic
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key IN (${keysToMove.map(() => '?').join(',')})
      `);
            const result = updateStmt.run(newChannel, testSessionId, ...keysToMove);
            (0, globals_1.expect)(result.changes).toBe(2);
            // Verify the changes
            const movedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, newChannel);
            (0, globals_1.expect)(movedItems.length).toBe(2);
            (0, globals_1.expect)(movedItems.every((item) => item.channel === newChannel)).toBe(true);
            (0, globals_1.expect)(movedItems.map((item) => item.key).sort()).toEqual(keysToMove.sort());
            // Handler response
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            keys: keysToMove,
                            newChannel: newChannel,
                            itemsUpdated: result.changes,
                            success: true,
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.itemsUpdated).toBe(2);
            (0, globals_1.expect)(parsed.success).toBe(true);
        });
        (0, globals_1.it)('should handle non-existent keys gracefully', () => {
            const keysToMove = ['non.existent.key1', 'non.existent.key2'];
            const newChannel = 'production';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key IN (${keysToMove.map(() => '?').join(',')})
      `);
            const result = updateStmt.run(newChannel, testSessionId, ...keysToMove);
            (0, globals_1.expect)(result.changes).toBe(0);
            // Handler response
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            keys: keysToMove,
                            newChannel: newChannel,
                            itemsUpdated: 0,
                            warning: 'No items found matching the specified keys',
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.itemsUpdated).toBe(0);
            (0, globals_1.expect)(parsed.warning).toBeTruthy();
        });
        (0, globals_1.it)('should not reassign items from other sessions', () => {
            const keysToMove = ['other.session.item'];
            const newChannel = 'production';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key IN (${keysToMove.map(() => '?').join(',')})
      `);
            const result = updateStmt.run(newChannel, testSessionId, ...keysToMove);
            (0, globals_1.expect)(result.changes).toBe(0);
            // Verify item wasn't moved
            const item = db
                .prepare('SELECT * FROM context_items WHERE key = ?')
                .get('other.session.item');
            (0, globals_1.expect)(item.channel).toBe('main'); // Original channel
            (0, globals_1.expect)(item.session_id).toBe(secondSessionId);
        });
        (0, globals_1.it)('should handle empty keys array', () => {
            const keysToMove = [];
            const _newChannel = 'production';
            // Handler should validate input
            try {
                if (keysToMove.length === 0) {
                    throw new validation_1.ValidationError('Keys array cannot be empty');
                }
            }
            catch (_error) {
                (0, globals_1.expect)(_error).toBeInstanceOf(validation_1.ValidationError);
                (0, globals_1.expect)(_error.message).toContain('Keys array cannot be empty');
            }
        });
    });
    (0, globals_1.describe)('Reassign by Key Pattern', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should reassign items matching key pattern', () => {
            const keyPattern = 'config.*';
            const newChannel = 'configuration';
            // Convert pattern to SQL GLOB pattern
            const globPattern = keyPattern.replace(/\*/g, '%');
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key LIKE ?
      `);
            const result = updateStmt.run(newChannel, testSessionId, globPattern);
            // Should update config.database.url and config.cache.ttl (not feature.auth.* or dev.*)
            (0, globals_1.expect)(result.changes).toBe(2);
            // Verify the changes
            const movedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, newChannel);
            (0, globals_1.expect)(movedItems.length).toBe(2);
            (0, globals_1.expect)(movedItems.every((item) => item.key.startsWith('config.'))).toBe(true);
        });
        (0, globals_1.it)('should handle complex patterns', () => {
            const keyPattern = 'feature.*.enabled';
            const newChannel = 'feature-flags';
            // This pattern should match keys like feature.auth.enabled
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key GLOB ?
      `);
            const result = updateStmt.run(newChannel, testSessionId, keyPattern);
            (0, globals_1.expect)(result.changes).toBe(1);
            const movedItem = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND key = ?')
                .get(testSessionId, 'feature.auth.enabled');
            (0, globals_1.expect)(movedItem.channel).toBe('feature-flags');
        });
        (0, globals_1.it)('should combine pattern with other filters', () => {
            const keyPattern = '*.*';
            const category = 'config';
            const newChannel = 'settings';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key GLOB ? AND category = ?
      `);
            const _result = updateStmt.run(newChannel, testSessionId, keyPattern, category);
            // Should update all config items with dot notation keys
            const movedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, newChannel);
            (0, globals_1.expect)(movedItems.every((item) => item.category === 'config')).toBe(true);
            (0, globals_1.expect)(movedItems.every((item) => item.key.includes('.'))).toBe(true);
        });
        (0, globals_1.it)('should handle pattern with no matches', () => {
            const keyPattern = 'nonexistent.*';
            const newChannel = 'nowhere';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key GLOB ?
      `);
            const result = updateStmt.run(newChannel, testSessionId, keyPattern);
            (0, globals_1.expect)(result.changes).toBe(0);
            // Handler response
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            keyPattern: keyPattern,
                            newChannel: newChannel,
                            itemsUpdated: 0,
                            warning: 'No items found matching the pattern',
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.warning).toBeTruthy();
        });
    });
    (0, globals_1.describe)('Reassign Entire Channel', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should move all items from one channel to another', () => {
            const fromChannel = 'feature/auth';
            const toChannel = 'release/v1.0';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ?
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel);
            (0, globals_1.expect)(result.changes).toBe(3); // All feature/auth items
            // Verify no items remain in old channel
            const oldChannelItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, fromChannel);
            (0, globals_1.expect)(oldChannelItems.length).toBe(0);
            // Verify all items moved to new channel
            const newChannelItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, toChannel);
            (0, globals_1.expect)(newChannelItems.length).toBe(3);
        });
        (0, globals_1.it)('should handle channel merge conflicts', () => {
            // Add an item to target channel first
            db.prepare(`
        INSERT INTO context_items (id, session_id, key, value, channel)
        VALUES (?, ?, ?, ?, ?)
      `).run((0, uuid_1.v4)(), testSessionId, 'existing.item', 'Already in production', 'production');
            const fromChannel = 'main';
            const toChannel = 'production';
            // Get count before merge
            const beforeCount = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ? AND channel = ?')
                .get(testSessionId, toChannel).count;
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ?
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel);
            // Get count after merge
            const afterCount = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ? AND channel = ?')
                .get(testSessionId, toChannel).count;
            (0, globals_1.expect)(afterCount).toBe(beforeCount + result.changes);
        });
        (0, globals_1.it)('should not move items when source channel is empty', () => {
            const fromChannel = 'non-existent-channel';
            const toChannel = 'production';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ?
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel);
            (0, globals_1.expect)(result.changes).toBe(0);
        });
    });
    (0, globals_1.describe)('Filtered Reassignment', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should reassign with category filter', () => {
            const fromChannel = 'main';
            const toChannel = 'tasks';
            const category = 'task';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ? AND category = ?
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel, category);
            (0, globals_1.expect)(result.changes).toBe(1); // Only task.deploy.status
            // Verify only tasks moved
            const movedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, toChannel);
            (0, globals_1.expect)(movedItems.every((item) => item.category === 'task')).toBe(true);
            // Verify config items stayed in main
            const remainingItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, fromChannel);
            (0, globals_1.expect)(remainingItems.some((item) => item.category === 'config')).toBe(true);
        });
        (0, globals_1.it)('should reassign with priority filter', () => {
            const fromChannel = 'feature/auth';
            const toChannel = 'critical';
            const priorities = ['high'];
            const placeholders = priorities.map(() => '?').join(',');
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ? AND priority IN (${placeholders})
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel, ...priorities);
            (0, globals_1.expect)(result.changes).toBe(2); // feature.auth.enabled and task.auth.implement
            // Verify only high priority items moved
            const movedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, toChannel);
            (0, globals_1.expect)(movedItems.every((item) => item.priority === 'high')).toBe(true);
        });
        (0, globals_1.it)('should reassign with multiple filters combined', () => {
            const keyPattern = 'feature.*';
            const category = 'config';
            const priorities = ['high', 'normal'];
            const newChannel = 'feature-config';
            const placeholders = priorities.map(() => '?').join(',');
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? 
          AND key GLOB ? 
          AND category = ? 
          AND priority IN (${placeholders})
      `);
            const result = updateStmt.run(newChannel, testSessionId, keyPattern, category, ...priorities);
            // Should match feature.auth.enabled and feature.auth.provider
            (0, globals_1.expect)(result.changes).toBe(2);
            const movedItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, newChannel);
            (0, globals_1.expect)(movedItems.every((item) => item.key.startsWith('feature.'))).toBe(true);
            (0, globals_1.expect)(movedItems.every((item) => item.category === 'config')).toBe(true);
        });
    });
    (0, globals_1.describe)('Dry Run Support', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should preview changes without applying them', () => {
            const fromChannel = 'main';
            const toChannel = 'production';
            const _dryRun = true;
            // In dry run, we SELECT instead of UPDATE
            const previewStmt = db.prepare(`
        SELECT id, key, value, category, priority, channel
        FROM context_items 
        WHERE session_id = ? AND channel = ?
      `);
            const itemsToMove = previewStmt.all(testSessionId, fromChannel);
            (0, globals_1.expect)(itemsToMove.length).toBe(3);
            // Verify no actual changes were made
            const originalItems = db
                .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, fromChannel);
            (0, globals_1.expect)(originalItems.length).toBe(3); // Still in original channel
            // Handler response for dry run
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            dryRun: true,
                            fromChannel: fromChannel,
                            toChannel: toChannel,
                            itemsToMove: itemsToMove.map((item) => ({
                                key: item.key,
                                value: item.value.substring(0, 50) + (item.value.length > 50 ? '...' : ''),
                                category: item.category,
                                priority: item.priority,
                            })),
                            totalItems: itemsToMove.length,
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.dryRun).toBe(true);
            (0, globals_1.expect)(parsed.totalItems).toBe(3);
            (0, globals_1.expect)(parsed.itemsToMove).toHaveLength(3);
        });
        (0, globals_1.it)('should preview pattern-based reassignment', () => {
            const keyPattern = 'config.*';
            const newChannel = 'settings';
            const _dryRun = true;
            const previewStmt = db.prepare(`
        SELECT id, key, value, category, priority, channel
        FROM context_items 
        WHERE session_id = ? AND key LIKE ?
      `);
            const itemsToMove = previewStmt.all(testSessionId, keyPattern.replace(/\*/g, '%'));
            (0, globals_1.expect)(itemsToMove.length).toBe(2);
            // Handler response
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            dryRun: true,
                            keyPattern: keyPattern,
                            newChannel: newChannel,
                            itemsToMove: itemsToMove.map((item) => ({
                                key: item.key,
                                currentChannel: item.channel,
                                category: item.category,
                                priority: item.priority,
                            })),
                            totalItems: itemsToMove.length,
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.totalItems).toBe(2);
            (0, globals_1.expect)(parsed.itemsToMove.every((item) => item.key.startsWith('config.'))).toBe(true);
        });
        (0, globals_1.it)('should show empty preview when no matches', () => {
            const keyPattern = 'nonexistent.*';
            const newChannel = 'nowhere';
            const _dryRun = true;
            const previewStmt = db.prepare(`
        SELECT id, key, value, category, priority, channel
        FROM context_items 
        WHERE session_id = ? AND key GLOB ?
      `);
            const itemsToMove = previewStmt.all(testSessionId, keyPattern);
            (0, globals_1.expect)(itemsToMove.length).toBe(0);
            // Handler response
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            dryRun: true,
                            keyPattern: keyPattern,
                            newChannel: newChannel,
                            itemsToMove: [],
                            totalItems: 0,
                            message: 'No items would be moved',
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.totalItems).toBe(0);
            (0, globals_1.expect)(parsed.message).toBeTruthy();
        });
    });
    (0, globals_1.describe)('Handler Response Formats', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should return detailed response for successful reassignment', () => {
            const keys = ['config.database.url', 'config.cache.ttl'];
            const newChannel = 'production';
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key IN (${keys.map(() => '?').join(',')})
      `);
            const result = updateStmt.run(newChannel, testSessionId, ...keys);
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            method: 'keys',
                            keys: keys,
                            newChannel: newChannel,
                            itemsUpdated: result.changes,
                            timestamp: new Date().toISOString(),
                            success: true,
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.method).toBe('keys');
            (0, globals_1.expect)(parsed.itemsUpdated).toBe(2);
            (0, globals_1.expect)(parsed.success).toBe(true);
            (0, globals_1.expect)(parsed.timestamp).toBeTruthy();
        });
        (0, globals_1.it)('should return summary for channel-to-channel move', () => {
            const fromChannel = 'feature/auth';
            const toChannel = 'release/v1.0';
            // Get items before move
            const itemsBefore = db
                .prepare('SELECT key FROM context_items WHERE session_id = ? AND channel = ?')
                .all(testSessionId, fromChannel);
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ?
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel);
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            method: 'channel',
                            fromChannel: fromChannel,
                            toChannel: toChannel,
                            itemsUpdated: result.changes,
                            movedKeys: itemsBefore.map((item) => item.key),
                            timestamp: new Date().toISOString(),
                            success: true,
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.method).toBe('channel');
            (0, globals_1.expect)(parsed.movedKeys).toHaveLength(3);
            (0, globals_1.expect)(parsed.fromChannel).toBe('feature/auth');
            (0, globals_1.expect)(parsed.toChannel).toBe('release/v1.0');
        });
        (0, globals_1.it)('should include filter details in response', () => {
            const keyPattern = 'config.*';
            const category = 'config';
            const priorities = ['high'];
            const newChannel = 'critical-config';
            const placeholders = priorities.map(() => '?').join(',');
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? 
          AND key LIKE ? 
          AND category = ? 
          AND priority IN (${placeholders})
      `);
            const result = updateStmt.run(newChannel, testSessionId, keyPattern.replace(/\*/g, '%'), category, ...priorities);
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            operation: 'reassign_channel',
                            method: 'filtered',
                            filters: {
                                keyPattern: keyPattern,
                                category: category,
                                priorities: priorities,
                            },
                            newChannel: newChannel,
                            itemsUpdated: result.changes,
                            success: true,
                        }, null, 2),
                    },
                ],
            };
            const parsed = JSON.parse(handlerResponse.content[0].text);
            (0, globals_1.expect)(parsed.method).toBe('filtered');
            (0, globals_1.expect)(parsed.filters).toEqual({
                keyPattern: keyPattern,
                category: category,
                priorities: priorities,
            });
        });
    });
    (0, globals_1.describe)('Error Handling', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should validate channel name', () => {
            const invalidChannels = ['', '  ', null, undefined];
            invalidChannels.forEach(invalidChannel => {
                try {
                    if (!invalidChannel || !invalidChannel.trim()) {
                        throw new validation_1.ValidationError('Channel name cannot be empty');
                    }
                }
                catch (_error) {
                    (0, globals_1.expect)(_error).toBeInstanceOf(validation_1.ValidationError);
                    (0, globals_1.expect)(_error.message).toContain('Channel name cannot be empty');
                }
            });
        });
        (0, globals_1.it)('should handle database errors gracefully', () => {
            // Close database to simulate error
            dbManager.close();
            try {
                db.prepare('UPDATE context_items SET channel = ? WHERE session_id = ?').run('new-channel', testSessionId);
            }
            catch (_error) {
                (0, globals_1.expect)(_error).toBeTruthy();
            }
        });
        (0, globals_1.it)('should validate reassignment parameters', () => {
            // No keys, pattern, or fromChannel provided
            const args = {
                toChannel: 'production',
            };
            try {
                if (!args.keys && !args.keyPattern && !args.fromChannel) {
                    throw new validation_1.ValidationError('Must provide either keys array, keyPattern, or fromChannel');
                }
            }
            catch (_error) {
                (0, globals_1.expect)(_error).toBeInstanceOf(validation_1.ValidationError);
                (0, globals_1.expect)(_error.message).toContain('Must provide either');
            }
        });
        (0, globals_1.it)('should prevent reassigning to same channel', () => {
            const fromChannel = 'main';
            const toChannel = 'main';
            try {
                if (fromChannel === toChannel) {
                    throw new validation_1.ValidationError('Source and destination channels cannot be the same');
                }
            }
            catch (_error) {
                (0, globals_1.expect)(_error).toBeInstanceOf(validation_1.ValidationError);
                (0, globals_1.expect)(_error.message).toContain('cannot be the same');
            }
        });
        (0, globals_1.it)('should handle SQL injection in channel names', () => {
            const maliciousChannel = "'; DROP TABLE context_items; --";
            const keys = ['config.database.url'];
            // Parameterized queries should prevent injection
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key = ?
      `);
            const result = updateStmt.run(maliciousChannel, testSessionId, keys[0]);
            // Should work normally
            (0, globals_1.expect)(result.changes).toBe(1);
            // Verify table still exists
            const tableExists = db
                .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='context_items'")
                .get();
            (0, globals_1.expect)(tableExists).toBeTruthy();
            // Verify the channel was set correctly
            const item = db.prepare('SELECT * FROM context_items WHERE key = ?').get(keys[0]);
            (0, globals_1.expect)(item.channel).toBe(maliciousChannel);
        });
    });
    (0, globals_1.describe)('Transaction Support', () => {
        (0, globals_1.beforeEach)(() => {
            createTestData();
        });
        (0, globals_1.it)('should perform reassignment in a transaction', () => {
            const fromChannel = 'feature/auth';
            const toChannel = 'production';
            let itemsUpdated = 0;
            try {
                db.prepare('BEGIN TRANSACTION').run();
                // First, get the items that will be moved
                const itemsToMove = db
                    .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                    .all(testSessionId, fromChannel);
                // Update the items
                const updateStmt = db.prepare(`
          UPDATE context_items 
          SET channel = ?, updated_at = CURRENT_TIMESTAMP
          WHERE session_id = ? AND channel = ?
        `);
                const result = updateStmt.run(toChannel, testSessionId, fromChannel);
                itemsUpdated = result.changes;
                // Verify within transaction
                const movedItems = db
                    .prepare('SELECT * FROM context_items WHERE session_id = ? AND channel = ?')
                    .all(testSessionId, toChannel);
                (0, globals_1.expect)(movedItems.length).toBe(itemsToMove.length);
                db.prepare('COMMIT').run();
            }
            catch (_error) {
                db.prepare('ROLLBACK').run();
                throw _error;
            }
            (0, globals_1.expect)(itemsUpdated).toBe(3);
        });
        (0, globals_1.it)('should rollback on error', () => {
            const fromChannel = 'main';
            const toChannel = 'production';
            // Count items before transaction
            const countBefore = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ? AND channel = ?')
                .get(testSessionId, fromChannel).count;
            try {
                db.prepare('BEGIN TRANSACTION').run();
                // Start update
                const updateStmt = db.prepare(`
          UPDATE context_items 
          SET channel = ?, updated_at = CURRENT_TIMESTAMP
          WHERE session_id = ? AND channel = ?
        `);
                updateStmt.run(toChannel, testSessionId, fromChannel);
                // Simulate an error
                throw new Error('Simulated error');
            }
            catch (_error) {
                db.prepare('ROLLBACK').run();
            }
            // Count items after rollback
            const countAfter = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ? AND channel = ?')
                .get(testSessionId, fromChannel).count;
            (0, globals_1.expect)(countAfter).toBe(countBefore); // No changes
        });
    });
    (0, globals_1.describe)('Performance and Scalability', () => {
        (0, globals_1.it)('should handle large batch reassignments efficiently', () => {
            // Create 1000 items
            const stmt = db.prepare(`
        INSERT INTO context_items (id, session_id, key, value, channel)
        VALUES (?, ?, ?, ?, ?)
      `);
            for (let i = 0; i < 1000; i++) {
                stmt.run((0, uuid_1.v4)(), testSessionId, `bulk.item.${i.toString().padStart(4, '0')}`, `Bulk value ${i}`, 'bulk-source');
            }
            const fromChannel = 'bulk-source';
            const toChannel = 'bulk-target';
            const startTime = Date.now();
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND channel = ?
      `);
            const result = updateStmt.run(toChannel, testSessionId, fromChannel);
            const endTime = Date.now();
            (0, globals_1.expect)(result.changes).toBe(1000);
            (0, globals_1.expect)(endTime - startTime).toBeLessThan(1000); // Should complete within 1 second
            // Verify all items moved
            const remainingCount = db
                .prepare('SELECT COUNT(*) as count FROM context_items WHERE session_id = ? AND channel = ?')
                .get(testSessionId, fromChannel).count;
            (0, globals_1.expect)(remainingCount).toBe(0);
        });
        (0, globals_1.it)('should handle pattern matching on large datasets', () => {
            // Create items with various patterns
            const patterns = ['config', 'feature', 'task', 'dev', 'test'];
            const stmt = db.prepare(`
        INSERT INTO context_items (id, session_id, key, value, channel)
        VALUES (?, ?, ?, ?, ?)
      `);
            for (let i = 0; i < 500; i++) {
                const pattern = patterns[i % patterns.length];
                stmt.run((0, uuid_1.v4)(), testSessionId, `${pattern}.item.${i}`, `Value ${i}`, 'mixed-channel');
            }
            const keyPattern = 'config.*';
            const newChannel = 'config-channel';
            const startTime = Date.now();
            const updateStmt = db.prepare(`
        UPDATE context_items 
        SET channel = ?, updated_at = CURRENT_TIMESTAMP
        WHERE session_id = ? AND key GLOB ?
      `);
            const result = updateStmt.run(newChannel, testSessionId, keyPattern);
            const endTime = Date.now();
            (0, globals_1.expect)(result.changes).toBe(100); // 500 / 5 patterns
            (0, globals_1.expect)(endTime - startTime).toBeLessThan(500); // Should be fast
        });
    });
});
