/**
 * Browser-based UI tests using Puppeteer
 * Tests the actual browser rendering and JavaScript execution of pages
 */

const puppeteer = require('puppeteer');

const DEFAULT_TIMEOUT = 10000;  // Increased for pages with many network requests
const DEFAULT_WAIT = 3000;      // More time for JS to execute

class BrowserTester {
    constructor(baseUrl = 'http://127.0.0.1:5000') {
        this.baseUrl = baseUrl;
        this.browser = null;
        this.page = null;
    }

    async setup() {
        console.log('🚀 Starting browser test session...');
        this.browser = await puppeteer.launch({
            headless: true,
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });

        this.page = await this.browser.newPage();

        // Listen to console logs from the page
        this.page.on('console', msg => {
            const type = msg.type();
            const text = msg.text();
            console.log(`📝 [${type.toUpperCase()}] ${text}`);
        });

        // Listen to JavaScript errors
        this.page.on('pageerror', error => {
            console.log(`❌ [JS ERROR] ${error.message}`);
        });

        // Listen to failed requests
        this.page.on('requestfailed', request => {
            const url = request.url();
            const error = request.failure().errorText;
            // Only log 404s for important resources, ignore favicon etc.
            if (!url.includes('favicon') && !url.includes('.ico')) {
                console.log(`🔴 [REQUEST FAILED] ${url} - ${error}`);
            }
        });
    }

    async teardown() {
        if (this.browser) {
            await this.browser.close();
            console.log('🏁 Browser test session ended');
        }
    }

    async testPage(path, testName, customTests = null) {
        const url = `${this.baseUrl}${path}`;
        console.log(`\n📄 Testing ${testName}: ${url}`);

        try {
            await this.page.goto(url, {
                waitUntil: 'domcontentloaded',  // Don't wait for all network requests
                timeout: DEFAULT_TIMEOUT
            });

            console.log(`✅ ${testName} loaded successfully`);

            // Wait for JavaScript to execute
            await new Promise(resolve => setTimeout(resolve, DEFAULT_WAIT));

            // Basic checks for all pages
            const basicChecks = await this.page.evaluate(() => {
                return {
                    hasTitle: document.title.length > 0,
                    hasBody: document.body !== null,
                    hasNoJSErrors: !window.hasJavaScriptErrors, // This would need to be set by error handlers
                    bodyVisible: document.body && window.getComputedStyle(document.body).display !== 'none'
                };
            });

            console.log(`🔍 Basic checks for ${testName}:`);
            console.log(`   Has title: ${basicChecks.hasTitle}`);
            console.log(`   Has body: ${basicChecks.hasBody}`);
            console.log(`   Body visible: ${basicChecks.bodyVisible}`);

            // Run custom tests if provided
            if (customTests) {
                await customTests(this.page);
            }

            return { success: true, checks: basicChecks };

        } catch (error) {
            console.log(`❌ Error testing ${testName}: ${error.message}`);
            return { success: false, error: error.message };
        }
    }
}

// Custom test functions for specific pages
const metricsPageTests = async (page) => {
    console.log('🧪 Running metrics-specific tests...');

    // Check if metrics elements are present
    const metricsChecks = await page.evaluate(() => {
        const loading = document.getElementById('loading');
        const content = document.getElementById('metrics-content');
        const error = document.getElementById('error');
        const totalTokens = document.getElementById('total-tokens');
        const totalResearches = document.getElementById('total-researches');

        return {
            hasLoadingElement: !!loading,
            hasContentElement: !!content,
            hasErrorElement: !!error,
            hasTotalTokens: !!totalTokens,
            hasTotalResearches: !!totalResearches,
            loadingVisible: loading ? window.getComputedStyle(loading).display !== 'none' : false,
            contentVisible: content ? window.getComputedStyle(content).display !== 'none' : false,
            errorVisible: error ? window.getComputedStyle(error).display !== 'none' : false,
            tokenValue: totalTokens ? totalTokens.textContent : 'NOT FOUND',
            researchValue: totalResearches ? totalResearches.textContent : 'NOT FOUND'
        };
    });

    console.log('📊 Metrics page checks:');
    console.log(`   Loading visible: ${metricsChecks.loadingVisible}`);
    console.log(`   Content visible: ${metricsChecks.contentVisible}`);
    console.log(`   Error visible: ${metricsChecks.errorVisible}`);
    console.log(`   Total tokens: ${metricsChecks.tokenValue}`);
    console.log(`   Total researches: ${metricsChecks.researchValue}`);

    // Take screenshot for debugging
    try {
        await page.screenshot({ path: 'tests/ui_tests/screenshots/metrics-test.png' });
        console.log('📸 Screenshot saved: tests/ui_tests/screenshots/metrics-test.png');
    } catch (err) {
        console.log('⚠️ Could not save screenshot:', err.message);
    }
};

const researchPageTests = async (page) => {
    console.log('🧪 Running research page tests...');

    const researchChecks = await page.evaluate(() => {
        const queryInput = document.getElementById('query');
        const submitButton = document.querySelector('button[type="submit"]');
        const modeSelect = document.querySelector('select[name="mode"]');

        return {
            hasQueryInput: !!queryInput,
            hasSubmitButton: !!submitButton,
            hasModeSelect: !!modeSelect,
            queryInputEnabled: queryInput ? !queryInput.disabled : false,
            submitButtonEnabled: submitButton ? !submitButton.disabled : false
        };
    });

    console.log('🔍 Research page checks:');
    console.log(`   Has query input: ${researchChecks.hasQueryInput}`);
    console.log(`   Has submit button: ${researchChecks.hasSubmitButton}`);
    console.log(`   Has mode select: ${researchChecks.hasModeSelect}`);
    console.log(`   Query input enabled: ${researchChecks.queryInputEnabled}`);
    console.log(`   Submit button enabled: ${researchChecks.submitButtonEnabled}`);
};

const historyPageTests = async (page) => {
    console.log('🧪 Running history page tests...');

    const historyChecks = await page.evaluate(() => {
        const historyContainer = document.getElementById('history-container') ||
                               document.querySelector('.history-list') ||
                               document.querySelector('[data-testid="history"]');
        const searchInput = document.querySelector('input[type="search"]') ||
                           document.querySelector('input[placeholder*="search"]');

        return {
            hasHistoryContainer: !!historyContainer,
            hasSearchInput: !!searchInput,
            historyContainerVisible: historyContainer ? window.getComputedStyle(historyContainer).display !== 'none' : false
        };
    });

    console.log('📜 History page checks:');
    console.log(`   Has history container: ${historyChecks.hasHistoryContainer}`);
    console.log(`   Has search input: ${historyChecks.hasSearchInput}`);
    console.log(`   History container visible: ${historyChecks.historyContainerVisible}`);
};

const settingsPageTests = async (page) => {
    console.log('🧪 Running settings page tests...');

    const settingsChecks = await page.evaluate(() => {
        const forms = document.querySelectorAll('form');
        const inputs = document.querySelectorAll('input, select, textarea');
        const saveButtons = document.querySelectorAll('button[type="submit"]');
        // Also look for buttons with Save text
        const allButtons = document.querySelectorAll('button');
        const saveTextButtons = Array.from(allButtons).filter(btn =>
            btn.textContent.toLowerCase().includes('save')
        );

        return {
            hasForm: forms.length > 0,
            hasInputs: inputs.length > 0,
            hasSaveButtons: saveButtons.length > 0 || saveTextButtons.length > 0,
            inputCount: inputs.length,
            formCount: forms.length
        };
    });

    console.log('⚙️ Settings page checks:');
    console.log(`   Has forms: ${settingsChecks.hasForm} (${settingsChecks.formCount} forms)`);
    console.log(`   Has inputs: ${settingsChecks.hasInputs} (${settingsChecks.inputCount} inputs)`);
    console.log(`   Has save buttons: ${settingsChecks.hasSaveButtons}`);
};

// Main test runner
async function runAllTests() {
    const tester = new BrowserTester();
    await tester.setup();

    // Ensure screenshots directory exists
    await tester.page.evaluate(() => {
        // This runs in browser context, can't create directories
    });

    const results = [];

    // Test main pages
    const testCases = [
        { path: '/', name: 'Home/Research Page', tests: researchPageTests },
        { path: '/metrics/', name: 'Metrics Dashboard', tests: metricsPageTests },
        { path: '/history/', name: 'History Page', tests: historyPageTests },
        { path: '/settings/', name: 'Settings Page', tests: settingsPageTests }
    ];

    for (const testCase of testCases) {
        const result = await tester.testPage(testCase.path, testCase.name, testCase.tests);
        results.push({ ...testCase, result });
    }

    await tester.teardown();

    // Print summary
    console.log('\n' + '='.repeat(50));
    console.log('📋 TEST SUMMARY');
    console.log('='.repeat(50));

    let passCount = 0;
    let failCount = 0;

    results.forEach(({ name, result }) => {
        const status = result.success ? '✅ PASS' : '❌ FAIL';
        console.log(`${status} ${name}`);
        if (!result.success) {
            console.log(`     Error: ${result.error}`);
            failCount++;
        } else {
            passCount++;
        }
    });

    console.log('\n' + '-'.repeat(30));
    console.log(`Total: ${results.length} tests`);
    console.log(`Passed: ${passCount}`);
    console.log(`Failed: ${failCount}`);

    if (failCount === 0) {
        console.log('🎉 All tests passed!');
        process.exit(0);
    } else {
        console.log('💥 Some tests failed!');
        process.exit(1);
    }
}

// Run tests if this file is executed directly
if (require.main === module) {
    runAllTests().catch(console.error);
}

module.exports = { BrowserTester, runAllTests };
