"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");
(0, globals_1.describe)('Enhanced Context Timeline Handler Integration Tests', () => {
    let dbManager;
    let tempDbPath;
    let db;
    let contextRepo;
    let testSessionId;
    (0, globals_1.beforeEach)(() => {
        tempDbPath = path.join(os.tmpdir(), `test-enhanced-timeline-${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 session
        testSessionId = (0, uuid_1.v4)();
        db.prepare('INSERT INTO sessions (id, name) VALUES (?, ?)').run(testSessionId, 'Test Session');
    });
    (0, globals_1.afterEach)(() => {
        dbManager.close();
        try {
            fs.unlinkSync(tempDbPath);
            fs.unlinkSync(`${tempDbPath}-wal`);
            fs.unlinkSync(`${tempDbPath}-shm`);
        }
        catch (_e) {
            // Ignore
        }
    });
    function createTestDataWithTimeline() {
        // TIMEZONE-SAFE PATTERN: Use fixed UTC dates to ensure consistent behavior
        // across all environments regardless of system timezone
        // Create a fixed reference point in UTC (2025-06-20 12:00:00 UTC)
        // This ensures consistent timeline grouping in all environments
        const baseDate = new Date('2025-06-20T12:00:00.000Z');
        // Create calendar-day-aligned dates in UTC by using UTC methods
        const today = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate(), 12, 0, 0));
        const yesterday = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - 1, 12, 0, 0));
        const threeDaysAgo = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - 3, 12, 0, 0));
        const fiveDaysAgo = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - 5, 12, 0, 0));
        const sevenDaysAgo = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - 7, 12, 0, 0));
        // Create items across different time periods
        const items = [
            // Today - 6 items (all at noon on same day)
            { time: new Date(today.getTime() + 1 * 60 * 60 * 1000), category: 'task', priority: 'high' },
            {
                time: new Date(today.getTime() + 2 * 60 * 60 * 1000),
                category: 'task',
                priority: 'normal',
            },
            {
                time: new Date(today.getTime() + 3 * 60 * 60 * 1000),
                category: 'note',
                priority: 'normal',
            },
            {
                time: new Date(today.getTime() + 4 * 60 * 60 * 1000),
                category: 'decision',
                priority: 'high',
            },
            {
                time: new Date(today.getTime() + 5 * 60 * 60 * 1000),
                category: 'progress',
                priority: 'normal',
            },
            { time: new Date(today.getTime() + 6 * 60 * 60 * 1000), category: 'task', priority: 'low' },
            // Yesterday - 3 items (all on previous day)
            {
                time: new Date(yesterday.getTime() + 1 * 60 * 60 * 1000),
                category: 'task',
                priority: 'high',
            },
            {
                time: new Date(yesterday.getTime() + 2 * 60 * 60 * 1000),
                category: 'note',
                priority: 'normal',
            },
            {
                time: new Date(yesterday.getTime() + 3 * 60 * 60 * 1000),
                category: 'progress',
                priority: 'low',
            },
            // 3 days ago - 1 item
            {
                time: new Date(threeDaysAgo.getTime() + 1 * 60 * 60 * 1000),
                category: 'decision',
                priority: 'high',
            },
            // 5 days ago - 2 items
            {
                time: new Date(fiveDaysAgo.getTime() + 1 * 60 * 60 * 1000),
                category: 'task',
                priority: 'normal',
            },
            {
                time: new Date(fiveDaysAgo.getTime() + 2 * 60 * 60 * 1000),
                category: 'note',
                priority: 'normal',
            },
            // 7 days ago - 4 items (all on same day)
            {
                time: new Date(sevenDaysAgo.getTime() + 1 * 60 * 60 * 1000),
                category: 'progress',
                priority: 'high',
            },
            {
                time: new Date(sevenDaysAgo.getTime() + 2 * 60 * 60 * 1000),
                category: 'task',
                priority: 'normal',
            },
            {
                time: new Date(sevenDaysAgo.getTime() + 3 * 60 * 60 * 1000),
                category: 'decision',
                priority: 'low',
            },
            {
                time: new Date(sevenDaysAgo.getTime() + 4 * 60 * 60 * 1000),
                category: 'note',
                priority: 'normal',
            },
        ];
        const stmt = db.prepare(`
      INSERT INTO context_items (
        id, session_id, key, value, category, priority, channel, created_at, updated_at, size
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `);
        items.forEach((item, index) => {
            const key = `item.${item.time.toISOString().split('T')[0]}.${index}`;
            const value = `Test item created at ${item.time.toISOString()}`;
            stmt.run((0, uuid_1.v4)(), testSessionId, key, value, item.category, item.priority, 'test-channel', item.time.toISOString(), item.time.toISOString(), Buffer.byteLength(value, 'utf8'));
        });
        return items;
    }
    (0, globals_1.describe)('minItemsPerPeriod Tests', () => {
        (0, globals_1.beforeEach)(() => {
            createTestDataWithTimeline();
        });
        (0, globals_1.it)('should filter periods with fewer items than minItemsPerPeriod', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 3,
            });
            // Only today (6 items), yesterday (3 items), and 7 days ago (4 items) should appear
            (0, globals_1.expect)(timeline.length).toBe(3);
            (0, globals_1.expect)(timeline.every((period) => period.count >= 3)).toBe(true);
        });
        (0, globals_1.it)('should include all periods when minItemsPerPeriod is 0', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 0,
            });
            // Should include all 5 periods that have data:
            // - Today (2025-06-20): 6 items
            // - Yesterday (2025-06-19): 3 items
            // - 3 days ago (2025-06-17): 1 item
            // - 5 days ago (2025-06-15): 2 items
            // - 7 days ago (2025-06-13): 4 items
            (0, globals_1.expect)(timeline.length).toBe(5);
        });
        (0, globals_1.it)('should handle negative minItemsPerPeriod by treating as 0', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: -5,
            });
            // Should include all periods (same as 0)
            (0, globals_1.expect)(timeline.length).toBe(5);
        });
        (0, globals_1.it)('should work with category filters and minItemsPerPeriod', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                categories: ['task'],
                minItemsPerPeriod: 2,
            });
            // Only today (3 task items) and 7 days ago (1 task, but need to verify) should qualify
            // Actually checking: today has 3 tasks, yesterday has 1 task, 7 days ago has 1 task
            // So only today qualifies with 2+ task items
            (0, globals_1.expect)(timeline.every((period) => period.count >= 2)).toBe(true);
        });
        (0, globals_1.it)('should work with hour grouping and minItemsPerPeriod', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'hour',
                minItemsPerPeriod: 1,
                relativeTime: 'today',
            });
            // Should only show hours that have at least 1 item
            (0, globals_1.expect)(timeline.every((period) => period.count >= 1)).toBe(true);
        });
        (0, globals_1.it)('should include item details when requested with minItemsPerPeriod filter', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 3,
                includeItems: true,
                itemsPerPeriod: 5,
            });
            // Check that periods have items attached
            timeline.forEach((period) => {
                (0, globals_1.expect)(period.items).toBeDefined();
                (0, globals_1.expect)(Array.isArray(period.items)).toBe(true);
                (0, globals_1.expect)(period.items.length).toBeLessThanOrEqual(5);
                (0, globals_1.expect)(period.count).toBeGreaterThanOrEqual(3);
            });
        });
        (0, globals_1.it)('should work with relative time and minItemsPerPeriod', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                relativeTime: '7 days ago',
                groupBy: 'day',
                minItemsPerPeriod: 2,
            });
            // Should include periods from last 7 days with 2+ items
            timeline.forEach((period) => {
                (0, globals_1.expect)(period.count).toBeGreaterThanOrEqual(2);
            });
        });
    });
    (0, globals_1.describe)('showEmpty Tests', () => {
        (0, globals_1.beforeEach)(() => {
            createTestDataWithTimeline();
        });
        (0, globals_1.it)('should generate empty periods when showEmpty is true', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 10, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
            });
            // Should have 11 periods (10 days + today)
            (0, globals_1.expect)(timeline.length).toBe(11);
            // Check that empty periods have count = 0
            const emptyPeriods = timeline.filter((p) => p.count === 0);
            (0, globals_1.expect)(emptyPeriods.length).toBeGreaterThan(0);
            emptyPeriods.forEach((period) => {
                (0, globals_1.expect)(period.count).toBe(0);
                (0, globals_1.expect)(period.items).toEqual([]);
            });
        });
        (0, globals_1.it)('should handle showEmpty with hour grouping', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(endDate.getTime() - 24 * 60 * 60 * 1000);
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'hour',
                showEmpty: true,
            });
            // Should have 25 periods (24 hours + current hour)
            (0, globals_1.expect)(timeline.length).toBe(25);
        });
        (0, globals_1.it)('should handle showEmpty with week grouping', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 28, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'week',
                showEmpty: true,
            });
            // Should have 5 periods (4 full weeks + current week)
            (0, globals_1.expect)(timeline.length).toBeGreaterThanOrEqual(4);
            (0, globals_1.expect)(timeline.length).toBeLessThanOrEqual(5);
        });
        (0, globals_1.it)('should include empty periods with categories filter', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 5, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                categories: ['task'],
                showEmpty: true,
            });
            // Should have 6 periods regardless of task items
            (0, globals_1.expect)(timeline.length).toBe(6);
        });
        (0, globals_1.it)('should handle showEmpty with relative time', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                relativeTime: '3 days ago',
                groupBy: 'day',
                showEmpty: true,
            });
            // Should have 4 periods (3 days ago to today)
            (0, globals_1.expect)(timeline.length).toBe(4);
        });
        (0, globals_1.it)('should enforce reasonable limits on empty period generation', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear() - 1, endDate.getUTCMonth(), endDate.getUTCDate(), 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
            });
            // Should enforce a reasonable limit (e.g., 365 days max)
            (0, globals_1.expect)(timeline.length).toBeLessThanOrEqual(365);
        });
        (0, globals_1.it)('should include items in non-empty periods when showEmpty is true', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 3, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
                includeItems: true,
            });
            // Find periods with data
            const nonEmptyPeriods = timeline.filter((p) => p.count > 0);
            (0, globals_1.expect)(nonEmptyPeriods.length).toBeGreaterThan(0);
            nonEmptyPeriods.forEach((period) => {
                (0, globals_1.expect)(period.items).toBeDefined();
                (0, globals_1.expect)(period.items.length).toBeGreaterThan(0);
            });
            // Empty periods should have empty items array
            const emptyPeriods = timeline.filter((p) => p.count === 0);
            emptyPeriods.forEach((period) => {
                (0, globals_1.expect)(period.items).toEqual([]);
            });
        });
    });
    (0, globals_1.describe)('Parameter Interaction Tests', () => {
        (0, globals_1.beforeEach)(() => {
            createTestDataWithTimeline();
        });
        (0, globals_1.it)('should have showEmpty override minItemsPerPeriod', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 5, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
                minItemsPerPeriod: 3,
            });
            // Should show all 6 days, including empty ones
            (0, globals_1.expect)(timeline.length).toBe(6);
            // Should include periods with 0 items despite minItemsPerPeriod
            const emptyPeriods = timeline.filter((p) => p.count === 0);
            (0, globals_1.expect)(emptyPeriods.length).toBeGreaterThan(0);
        });
        (0, globals_1.it)('should work with all parameters combined', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 7, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                categories: ['task', 'progress'],
                showEmpty: true,
                minItemsPerPeriod: 2,
                includeItems: true,
                itemsPerPeriod: 3,
            });
            // Should have 8 days total
            (0, globals_1.expect)(timeline.length).toBe(8);
            // Check various aspects
            timeline.forEach((period) => {
                (0, globals_1.expect)(period).toHaveProperty('period');
                (0, globals_1.expect)(period).toHaveProperty('count');
                (0, globals_1.expect)(period).toHaveProperty('items');
                if (period.count > 0) {
                    // Non-empty periods should respect itemsPerPeriod
                    (0, globals_1.expect)(period.items.length).toBeLessThanOrEqual(3);
                    // Items should only be from specified categories
                    period.items.forEach((item) => {
                        (0, globals_1.expect)(['task', 'progress']).toContain(item.category);
                    });
                }
            });
        });
        (0, globals_1.it)('should handle showEmpty false with minItemsPerPeriod', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                showEmpty: false,
                minItemsPerPeriod: 2,
            });
            // Should only show periods with 2+ items
            (0, globals_1.expect)(timeline.every((period) => period.count >= 2)).toBe(true);
            // Should not include any empty periods
            (0, globals_1.expect)(timeline.every((period) => period.count > 0)).toBe(true);
        });
        (0, globals_1.it)('should respect date ranges with both new parameters', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const baseDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - 2, 0, 0, 0));
            const endDate = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - 1, 23, 59, 59, 999));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
                minItemsPerPeriod: 5,
            });
            // Should show exactly 2 days
            (0, globals_1.expect)(timeline.length).toBe(2);
        });
    });
    (0, globals_1.describe)('Edge Cases and Validation Tests', () => {
        (0, globals_1.beforeEach)(() => {
            createTestDataWithTimeline();
        });
        (0, globals_1.it)('should handle minItemsPerPeriod larger than any period count', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 100,
            });
            // Should return empty array since no period has 100+ items
            (0, globals_1.expect)(timeline).toEqual([]);
        });
        (0, globals_1.it)('should handle showEmpty with no date range specified', () => {
            // Without date range, showEmpty should be ignored
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                showEmpty: true,
            });
            // Should only return periods with data
            (0, globals_1.expect)(timeline.every((period) => period.count > 0)).toBe(true);
        });
        (0, globals_1.it)('should handle invalid date ranges gracefully', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: '2025-01-01',
                endDate: '2024-01-01', // End before start
                groupBy: 'day',
                showEmpty: true,
            });
            // Should return empty array or handle gracefully
            (0, globals_1.expect)(timeline).toEqual([]);
        });
        (0, globals_1.it)('should handle very large minItemsPerPeriod values', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: Number.MAX_SAFE_INTEGER,
            });
            // Should return empty array
            (0, globals_1.expect)(timeline).toEqual([]);
        });
        (0, globals_1.it)('should handle fractional minItemsPerPeriod by rounding', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 2.7, // Should be treated as 3
            });
            // Periods should have at least 3 items
            (0, globals_1.expect)(timeline.every((period) => period.count >= 3)).toBe(true);
        });
        (0, globals_1.it)('should handle showEmpty with very narrow time windows', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const startDate = new Date('2025-06-20T12:00:00.000Z');
            const endDate = new Date(startDate.getTime() + 60 * 60 * 1000); // 1 hour later
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'hour',
                showEmpty: true,
            });
            // Should have 2 hour periods
            (0, globals_1.expect)(timeline.length).toBe(2);
        });
        (0, globals_1.it)('should maintain sort order with new parameters', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                showEmpty: false,
                minItemsPerPeriod: 1,
            });
            // Verify descending order by period
            for (let i = 1; i < timeline.length; i++) {
                (0, globals_1.expect)(timeline[i - 1].period >= timeline[i].period).toBe(true);
            }
        });
    });
    (0, globals_1.describe)('Performance Tests', () => {
        (0, globals_1.it)('should handle large datasets efficiently with minItemsPerPeriod', () => {
            // Create many items
            const stmt = db.prepare(`
        INSERT INTO context_items (
          id, session_id, key, value, category, channel, created_at, size
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
      `);
            const batchSize = 1000;
            const baseDate = new Date('2025-06-20T12:00:00.000Z');
            for (let i = 0; i < batchSize; i++) {
                const daysAgo = Math.floor(Math.random() * 30);
                const date = new Date(Date.UTC(baseDate.getUTCFullYear(), baseDate.getUTCMonth(), baseDate.getUTCDate() - daysAgo, 12, 0, 0));
                stmt.run((0, uuid_1.v4)(), testSessionId, `perf.test.${i}`, `Performance test item ${i}`, 'performance', 'test-channel', date.toISOString(), 20);
            }
            const startTime = Date.now();
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 10,
            });
            const endTime = Date.now();
            // Should complete within reasonable time
            (0, globals_1.expect)(endTime - startTime).toBeLessThan(500);
            // Should only show days with 10+ items
            (0, globals_1.expect)(timeline.every((period) => period.count >= 10)).toBe(true);
        });
        (0, globals_1.it)('should handle showEmpty efficiently for large date ranges', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 90, 12, 0, 0));
            const startTime = Date.now();
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
            });
            const endTime = Date.now();
            // Should complete within reasonable time
            (0, globals_1.expect)(endTime - startTime).toBeLessThan(1000);
            // Should have ~91 periods
            (0, globals_1.expect)(timeline.length).toBeGreaterThanOrEqual(90);
            (0, globals_1.expect)(timeline.length).toBeLessThanOrEqual(92);
        });
    });
    (0, globals_1.describe)('Backward Compatibility Tests', () => {
        (0, globals_1.beforeEach)(() => {
            createTestDataWithTimeline();
        });
        (0, globals_1.it)('should work without new parameters (existing behavior)', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
            });
            // Should return all periods with data
            (0, globals_1.expect)(timeline.length).toBeGreaterThan(0);
            (0, globals_1.expect)(timeline.every((period) => period.count > 0)).toBe(true);
        });
        (0, globals_1.it)('should maintain existing parameter functionality', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                categories: ['task'],
                includeItems: true,
                itemsPerPeriod: 2,
            });
            // Should filter by category and limit items
            timeline.forEach((period) => {
                if (period.items && period.items.length > 0) {
                    (0, globals_1.expect)(period.items.every((item) => item.category === 'task')).toBe(true);
                    (0, globals_1.expect)(period.items.length).toBeLessThanOrEqual(2);
                }
            });
        });
        (0, globals_1.it)('should handle undefined new parameters gracefully', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: undefined,
                showEmpty: undefined,
            });
            // Should behave as if parameters weren't provided
            (0, globals_1.expect)(timeline.length).toBeGreaterThan(0);
            (0, globals_1.expect)(timeline.every((period) => period.count > 0)).toBe(true);
        });
        (0, globals_1.it)('should maintain response format compatibility', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                includeItems: true,
            });
            // Verify expected structure
            timeline.forEach((period) => {
                (0, globals_1.expect)(period).toHaveProperty('period');
                (0, globals_1.expect)(period).toHaveProperty('count');
                (0, globals_1.expect)(period).toHaveProperty('items');
                (0, globals_1.expect)(typeof period.period).toBe('string');
                (0, globals_1.expect)(typeof period.count).toBe('number');
                (0, globals_1.expect)(Array.isArray(period.items)).toBe(true);
            });
        });
    });
    (0, globals_1.describe)('Handler Response Format Tests', () => {
        (0, globals_1.beforeEach)(() => {
            createTestDataWithTimeline();
        });
        (0, globals_1.it)('should format timeline response correctly', () => {
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                minItemsPerPeriod: 2,
            });
            // Simulate handler formatting
            const formattedPeriods = timeline
                .map((p) => `${p.period}: ${p.count} items${p.hasMore ? ` (showing ${p.items?.length || 0} of ${p.totalCount})` : ''}`)
                .join('\n');
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: `Timeline (${timeline.length} periods):\n\n${formattedPeriods}`,
                    },
                ],
            };
            (0, globals_1.expect)(handlerResponse.content[0].text).toContain('Timeline');
            (0, globals_1.expect)(handlerResponse.content[0].text).toContain('periods');
            (0, globals_1.expect)(handlerResponse.content[0].text).toContain('items');
        });
        (0, globals_1.it)('should include empty periods in response when showEmpty is true', () => {
            // Use UTC-based dates for consistent behavior across timezones
            const endDate = new Date('2025-06-20T12:00:00.000Z');
            const startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth(), endDate.getUTCDate() - 3, 12, 0, 0));
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                startDate: startDate.toISOString(),
                endDate: endDate.toISOString(),
                groupBy: 'day',
                showEmpty: true,
            });
            // Handler should indicate empty periods
            const formattedPeriods = timeline
                .map((p) => `${p.period}: ${p.count === 0 ? 'No items' : `${p.count} items`}`)
                .join('\n');
            (0, globals_1.expect)(formattedPeriods).toContain('No items');
        });
        (0, globals_1.it)('should format response with journal entries integration', () => {
            // Add journal entries
            db.prepare(`
        INSERT INTO journal_entries (id, session_id, entry, created_at)
        VALUES (?, ?, ?, ?)
      `).run((0, uuid_1.v4)(), testSessionId, 'Test journal entry', new Date('2025-06-20T12:00:00.000Z').toISOString());
            const timeline = contextRepo.getTimelineData({
                sessionId: testSessionId,
                groupBy: 'day',
                includeItems: true,
            });
            // Handler would merge context items and journal entries
            const handlerResponse = {
                content: [
                    {
                        type: 'text',
                        text: `Timeline with ${timeline.length} periods and journal entries`,
                    },
                ],
            };
            (0, globals_1.expect)(handlerResponse.content[0].text).toContain('journal entries');
        });
    });
});
