/**
 * Test Context Overflow Dashboard
 * Tests the context overflow analytics page functionality
 */

const puppeteer = require('puppeteer');
const AuthHelper = require('./auth_helper');

const BASE_URL = process.env.BASE_URL || 'http://127.0.0.1:5000';
const HEADLESS = process.env.HEADLESS !== 'false';
const SLOW_MO = parseInt(process.env.SLOW_MO || '0', 10);

describe('Context Overflow Dashboard Tests', () => {
    let browser;
    let page;
    let authHelper;

    beforeAll(async () => {
        browser = await puppeteer.launch({
            headless: HEADLESS,
            slowMo: SLOW_MO,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });
    });

    afterAll(async () => {
        if (browser) {
            await browser.close();
        }
    });

    beforeEach(async () => {
        page = await browser.newPage();
        await page.setViewport({ width: 1280, height: 800 });
        authHelper = new AuthHelper(page, BASE_URL);

        // Set longer timeout for slower operations
        page.setDefaultTimeout(30000);
    });

    afterEach(async () => {
        if (page) {
            await page.close();
        }
    });

    test('Context overflow dashboard loads and displays data', async () => {
        console.log('📊 Testing context overflow dashboard...');

        // Login first
        await authHelper.ensureAuthenticated();

        // Navigate to context overflow page
        console.log('  Navigating to context overflow page...');
        await page.goto(`${BASE_URL}/metrics/context-overflow`, {
            waitUntil: 'domcontentloaded',
            timeout: 30000
        });

        // Wait for page to load
        await page.waitForSelector('#context-overflow', { timeout: 10000 });
        console.log('  ✅ Context overflow page loaded');

        // Sanity-check that the controller JS was extracted out of the
        // template into its own deferred file. If someone re-inlines the
        // IIFE later, the deferred-script ordering bug returns silently.
        const externalScripts = await page.$$eval('script[defer][src]', els =>
            els.map(s => s.getAttribute('src'))
        );
        expect(externalScripts).toContain('/static/js/components/context-overflow.js');
        expect(externalScripts).toContain('/static/js/components/context-overflow-shared.js');

        // Wait for loading to complete
        console.log('  Waiting for data to load...');
        await page.waitForFunction(
            () => {
                const loading = document.getElementById('loading');
                const content = document.getElementById('content');
                return loading && loading.style.display === 'none' &&
                       content && content.style.display !== 'none';
            },
            { timeout: 15000 }
        );
        console.log('  ✅ Data loading complete');

        // Check for main sections
        const sections = await page.evaluate(() => {
            const results = {
                hasOverviewCards: false,
                hasContextChart: false,
                hasModelStats: false,
                hasTruncatedList: false,
                truncationRate: null,
                avgTokensLost: null,
                modelsTracked: null,
                dataCoverage: null
            };

            // Check overview cards
            const overviewCards = document.querySelector('.overflow-grid');
            results.hasOverviewCards = !!overviewCards;

            // Get metrics values
            const truncationRate = document.getElementById('truncation-rate');
            if (truncationRate) {
                results.truncationRate = truncationRate.textContent.trim();
            }

            const avgTokensLost = document.getElementById('avg-tokens-lost');
            if (avgTokensLost) {
                results.avgTokensLost = avgTokensLost.textContent.trim();
            }

            const modelsTracked = document.getElementById('models-tracked');
            if (modelsTracked) {
                results.modelsTracked = modelsTracked.textContent.trim();
            }

            const dataCoverage = document.getElementById('data-coverage');
            if (dataCoverage) {
                results.dataCoverage = dataCoverage.textContent.trim();
            }

            // Check charts
            const contextChart = document.getElementById('context-chart');
            results.hasContextChart = !!contextChart;

            // Check model stats section
            const modelStats = document.getElementById('model-stats');
            results.hasModelStats = !!modelStats;

            // Check truncated list section
            const truncatedList = document.getElementById('truncated-list');
            results.hasTruncatedList = !!truncatedList;

            return results;
        });

        console.log('  📊 Dashboard sections found:');
        console.log(`    - Overview cards: ${sections.hasOverviewCards ? '✅' : '❌'}`);
        console.log(`    - Context chart: ${sections.hasContextChart ? '✅' : '❌'}`);
        console.log(`    - Model stats: ${sections.hasModelStats ? '✅' : '❌'}`);
        console.log(`    - Truncated list: ${sections.hasTruncatedList ? '✅' : '❌'}`);

        console.log('  📈 Metrics values:');
        console.log(`    - Truncation rate: ${sections.truncationRate}`);
        console.log(`    - Avg tokens lost: ${sections.avgTokensLost}`);
        console.log(`    - Models tracked: ${sections.modelsTracked}`);
        console.log(`    - Data coverage: ${sections.dataCoverage}`);

        // Verify all main sections are present
        expect(sections.hasOverviewCards).toBe(true);
        expect(sections.hasContextChart).toBe(true);
        expect(sections.hasModelStats).toBe(true);
        expect(sections.hasTruncatedList).toBe(true);

        // Verify metrics are displayed (even if 0)
        expect(sections.truncationRate).not.toBeNull();
        expect(sections.avgTokensLost).not.toBeNull();
        expect(sections.modelsTracked).not.toBeNull();
        expect(sections.dataCoverage).not.toBeNull();
    });

    test('Time range selector works', async () => {
        console.log('🕐 Testing time range selector...');

        // Login first
        await authHelper.ensureAuthenticated();

        // Navigate to context overflow page
        await page.goto(`${BASE_URL}/metrics/context-overflow`, {
            waitUntil: 'domcontentloaded',
            timeout: 30000
        });

        // Wait for page to load
        await page.waitForSelector('.time-range-selector', { timeout: 10000 });

        // Get initial active period
        const initialPeriod = await page.evaluate(() => {
            const activeBtn = document.querySelector('.time-range-btn.active');
            return activeBtn ? activeBtn.getAttribute('data-period') : null;
        });
        console.log(`  Initial period: ${initialPeriod}`);

        // Try clicking different time periods
        const periods = ['7d', '30d', '3m', '1y', 'all'];

        for (const period of periods) {
            console.log(`  Testing period: ${period}`);

            // Click the time range button
            await page.click(`[data-period="${period}"]`);

            // Wait a moment for the request to start
            await new Promise(resolve => setTimeout(resolve, 500));

            // Verify the button is now active
            const isActive = await page.evaluate((p) => {
                const btn = document.querySelector(`[data-period="${p}"]`);
                return btn && btn.classList.contains('active');
            }, period);

            expect(isActive).toBe(true);
            console.log(`    ✅ ${period} button activated`);
        }
    });

    test('API endpoint returns data', async () => {
        console.log('🔌 Testing API endpoint...');

        // Login first
        await authHelper.ensureAuthenticated();

        // Get cookies for authenticated request
        const cookies = await page.cookies();
        const sessionCookie = cookies.find(c => c.name === 'session');

        if (!sessionCookie) {
            console.log('  ⚠️  No session cookie found');
            return;
        }

        // Make API request
        const response = await page.evaluate(async (baseUrl) => {
            try {
                const res = await fetch(`${baseUrl}/metrics/api/context-overflow?period=30d`, {
                    method: 'GET',
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json'
                    }
                });

                const data = await res.json();
                return {
                    status: res.status,
                    ok: res.ok,
                    data
                };
            } catch (error) {
                return {
                    error: error.message
                };
            }
        }, BASE_URL);

        console.log(`  API Response status: ${response.status}`);
        console.log(`  API Response OK: ${response.ok}`);

        if (response.data) {
            console.log(`  API Response status field: ${response.data.status}`);

            if (response.data.overview) {
                console.log('  📊 Overview data:');
                console.log(`    - Total requests: ${response.data.overview.total_requests}`);
                console.log(`    - Requests with context: ${response.data.overview.requests_with_context_data}`);
                console.log(`    - Truncated requests: ${response.data.overview.truncated_requests}`);
                console.log(`    - Truncation rate: ${response.data.overview.truncation_rate}%`);
            }

            if (response.data.model_stats) {
                console.log(`  📊 Model stats count: ${response.data.model_stats.length}`);
            }

            if (response.data.context_limits) {
                console.log(`  📊 Context limits count: ${response.data.context_limits.length}`);
            }

            if (response.data.chart_data) {
                console.log(`  📊 Chart data points: ${response.data.chart_data.length}`);
            }
        }

        // Verify response structure
        expect(response.status).toBe(200);
        expect(response.ok).toBe(true);
        expect(response.data).toBeDefined();
        expect(response.data.status).toBe('success');
        expect(response.data.overview).toBeDefined();
    });
});
