const puppeteer = require('puppeteer');
const fs = require('fs').promises;
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');

const BASE_URL = 'http://127.0.0.1:5000';
const TIMEOUT = 60000;

// Color codes for output
const colors = {
    info: '\x1b[36m',
    success: '\x1b[32m',
    warning: '\x1b[33m',
    error: '\x1b[31m',
    section: '\x1b[34m',
    reset: '\x1b[0m'
};

function log(message, type = 'info') {
    const timestamp = new Date().toLocaleTimeString();
    console.log(`${colors[type]}[${timestamp}] ${message}${colors.reset}`);
}

async function ensureAuthenticated(page, username, password) {
    log('Checking authentication status...', 'info');

    // Check if already authenticated
    try {
        await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });
        await page.waitForSelector('a.logout-btn', { timeout: 3000 });
        log('Already authenticated', 'success');
        return true;
    } catch {
        log('Not authenticated, need to register...', 'warning');
    }

    // Skip login attempt (it usually fails for new users) and go straight to registration
    log('Registering new user...', 'info');

    // Navigate to registration page
    await page.goto(`${BASE_URL}/auth/register`, { waitUntil: 'domcontentloaded' });

    // Wait for form to be ready
    await page.waitForSelector('#username', { visible: true });

    await page.type('#username', username);
    await page.type('#password', password);
    await page.type('#confirm_password', password);

    // Check the acknowledge checkbox if present
    const acknowledgeCheckbox = await page.$('#acknowledge');
    if (acknowledgeCheckbox) {
        await acknowledgeCheckbox.click();
    }

    await page.click('button[type="submit"]');

    // Wait for navigation after registration
    await page.waitForNavigation({ waitUntil: 'domcontentloaded' });

    const finalUrl = page.url();
    if (finalUrl === `${BASE_URL}/` || finalUrl.includes('/home')) {
        log('Registration successful', 'success');
        return true;
    }

    log(`Registration may have failed, current URL: ${finalUrl}`, 'warning');
    return false;
}

async function startResearch(page, query) {
    log(`Starting research: "${query}"`, 'info');

    await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });

    // Wait for form to be ready - try multiple selectors
    try {
        await page.waitForSelector('#query, #research_query, input[name="query"]', { visible: true, timeout: 5000 });
    } catch {
        log('Research form not found with expected selectors', 'warning');
    }

    // Type research query - use correct selector
    const queryInput = await page.$('#query') || await page.$('#research_query') || await page.$('input[name="query"]');
    if (queryInput) {
        await queryInput.type(query);
    } else {
        throw new Error('Could not find query input field');
    }

    // Submit form - use correct button selector
    const submitButton = await page.$('#start-research-btn') || await page.$('#submit-research') || await page.$('button[type="submit"]');
    if (submitButton) {
        await submitButton.click();
    } else {
        throw new Error('Could not find submit button');
    }

    // Wait for navigation to research page
    await page.waitForNavigation({ waitUntil: 'domcontentloaded' });

    // Wait for research to start
    await page.waitForSelector('.research-status, .status-indicator', { visible: true });

    log('Research started', 'success');

    // Get research ID from URL
    const url = page.url();
    const match = url.match(/\/research\/(\d+)/);
    return match ? match[1] : null;
}

async function waitForResearchProgress(page, _maxWaitTime = 5000) {
    log('Checking research submission...', 'info');

    // In CI, we don't wait for research to complete
    // Just verify it was submitted
    await new Promise(resolve => setTimeout(resolve, 3000));

    try {
        const currentUrl = page.url();
        if (currentUrl.includes('/progress/') || currentUrl.includes('/research/')) {
            log('Research submitted successfully', 'success');
            return true;
        }
    } catch {
        log('Could not check research status', 'warning');
    }

    log('Continuing without waiting for research completion', 'info');
    return true;
}

async function captureMetricsDashboard(page) {
    log('Navigating to metrics dashboard...', 'info');

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

    // Wait for metrics to load
    await page.waitForSelector('.metrics-container, .dashboard-container', { visible: true });

    // Give charts time to render
    await new Promise(resolve => setTimeout(resolve, 3000));

    // Capture metrics data
    const metricsData = await page.evaluate(() => {
        const data = {
            timestamp: new Date().toISOString(),
            url: window.location.href,
            tokenUsage: {},
            searchMetrics: {},
            charts: {},
            rawText: ''
        };

        // Get token usage stats
        const tokenStats = document.querySelectorAll('.token-stats, .usage-stats, .metric-card');
        tokenStats.forEach(stat => {
            const label = stat.querySelector('.metric-label, .stat-label, h3, h4');
            const value = stat.querySelector('.metric-value, .stat-value, .value, p');
            if (label && value) {
                data.tokenUsage[label.textContent.trim()] = value.textContent.trim();
            }
        });

        // Get search engine stats
        const searchStats = document.querySelectorAll('.search-stats, .engine-stats');
        searchStats.forEach(stat => {
            const engine = stat.querySelector('.engine-name, h4');
            const count = stat.querySelector('.call-count, .count');
            if (engine && count) {
                data.searchMetrics[engine.textContent.trim()] = count.textContent.trim();
            }
        });

        // Check for chart elements
        const charts = document.querySelectorAll('canvas, .chart-container');
        data.charts.count = charts.length;
        data.charts.types = Array.from(charts).map(c => c.className || c.tagName);

        // Get all text content from metrics page
        data.rawText = document.body.innerText;

        return data;
    });

    // Log what we found
    log('\n=== METRICS DASHBOARD DATA ===', 'section');
    log('Token Usage:', 'info');
    console.log(metricsData.tokenUsage);

    log('\nSearch Metrics:', 'info');
    console.log(metricsData.searchMetrics);

    log('\nCharts found: ' + metricsData.charts.count, 'info');

    // Check if we have any data
    const hasTokenData = Object.keys(metricsData.tokenUsage).length > 0;
    const hasSearchData = Object.keys(metricsData.searchMetrics).length > 0;

    if (!hasTokenData && !hasSearchData) {
        log('\nRAW PAGE CONTENT:', 'warning');
        console.log(metricsData.rawText.substring(0, 1000) + '...');
    }


    // Save metrics data
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const dataPath = `./metrics-data-${timestamp}.json`;
    await fs.writeFile(dataPath, JSON.stringify(metricsData, null, 2));
    log(`Metrics data saved: ${dataPath}`, 'success');

    return {
        hasTokenData,
        hasSearchData,
        metricsData
    };
}

async function testMetricsVerification() {
    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());

    const page = await browser.newPage();
    page.setDefaultTimeout(TIMEOUT);

    // Log console messages
    page.on('console', msg => {
        if (msg.type() === 'error') {
            log(`Browser console error: ${msg.text()}`, 'error');
        }
    });

    try {
        // Create unique user
        const timestamp = Date.now();
        const username = `metrics_test_${timestamp}`;
        const password = 'T3st!Secure#2024$LDR';

        log(`\n=== METRICS VERIFICATION TEST ===`, 'section');
        log(`Username: ${username}`, 'info');
        log(`Password: (secure password with special characters)`, 'info');

        // Authenticate
        await ensureAuthenticated(page, username, password);

        // Start a research
        log('\n=== STARTING RESEARCH ===', 'section');
        const researchId = await startResearch(page, "What are the benefits of solar energy?");
        log(`Research ID: ${researchId}`, 'info');

        // Wait for some progress
        await waitForResearchProgress(page);

        // Navigate around to generate more activity
        log('\n=== GENERATING ACTIVITY ===', 'section');

        // Go to history page
        await page.goto(`${BASE_URL}/history`, { waitUntil: 'domcontentloaded' });
        log('Visited history page', 'success');
        await new Promise(resolve => setTimeout(resolve, 2000));

        // Go back to research page
        if (researchId) {
            await page.goto(`${BASE_URL}/research/${researchId}`, { waitUntil: 'domcontentloaded' });
            log('Returned to research page', 'success');
            await new Promise(resolve => setTimeout(resolve, 3000));
        }

        // Go to settings
        await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });
        log('Visited settings page', 'success');
        await new Promise(resolve => setTimeout(resolve, 2000));

        // Capture metrics dashboard
        log('\n=== CAPTURING METRICS ===', 'section');
        const { hasTokenData, hasSearchData } = await captureMetricsDashboard(page);

        // Verify results
        log('\n=== VERIFICATION RESULTS ===', 'section');
        if (hasTokenData) {
            log('✅ Token usage metrics are displayed', 'success');
        } else {
            log('❌ No token usage metrics found', 'error');
        }

        if (hasSearchData) {
            log('✅ Search engine metrics are displayed', 'success');
        } else {
            log('❌ No search engine metrics found', 'error');
        }

        if (hasTokenData || hasSearchData) {
            log('\n✅ METRICS DASHBOARD IS WORKING!', 'success');
        } else {
            log('\n❌ METRICS DASHBOARD IS NOT DISPLAYING DATA', 'error');
        }

    } catch (error) {
        log(`\n❌ Test failed: ${error.message}`, 'error');
        console.error(error);
        process.exitCode = 1;
    } finally {
        // Close browser properly
        await browser.close();
    }
}

// Run the test
testMetricsVerification().catch(err => {
    console.error('❌ Unhandled error:', err);
    process.exitCode = 1;
});
