/**
 * Error Recovery UI Test
 * Tests how the UI handles various error conditions gracefully
 * CI-compatible: Works in both local and CI environments
 */

const puppeteer = require('puppeteer');
const AuthHelper = require('./auth_helper');
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');
const fs = require('fs');
const path = require('path');

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

async function testErrorRecovery() {
    const isCI = !!process.env.CI;
    console.log(`🧪 Running error recovery test (CI mode: ${isCI})`);

    // Create screenshots directory
    const screenshotsDir = path.join(__dirname, 'screenshots');
    if (!fs.existsSync(screenshotsDir)) {
        fs.mkdirSync(screenshotsDir, { recursive: true });
    }

    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
    const page = await browser.newPage();
    const auth = new AuthHelper(page, BASE_URL);

    // Set longer timeout for CI
    const timeout = isCI ? 60000 : 30000;
    page.setDefaultTimeout(timeout);
    page.setDefaultNavigationTimeout(timeout);

    let testsPassed = 0;
    let testsFailed = 0;

    // Track console errors
    const consoleErrors = [];
    page.on('console', msg => {
        if (msg.type() === 'error') {
            consoleErrors.push(msg.text());
        }
    });

    try {
        // Setup: Authenticate
        console.log('🔐 Authenticating...');
        await auth.ensureAuthenticatedWithTimeout();
        console.log('✅ Authentication successful\n');

        // Test 1: Invalid research query (empty)
        console.log('📝 Test 1: Empty query validation');
        try {
            await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });

            // Try to submit empty query
            const submitButton = await page.$('button[type="submit"]');
            if (submitButton) {
                await submitButton.click();
                await new Promise(resolve => setTimeout(resolve, 1000));

                // Check that we're still on the same page (form validation prevented submission)
                const currentUrl = page.url();
                if (currentUrl === `${BASE_URL}/` || currentUrl.includes('/auth/')) {
                    console.log('✅ Empty query was properly rejected');
                    testsPassed++;
                } else {
                    console.log('⚠️  Form submitted with empty query (may be expected)');
                    testsPassed++; // Some forms may allow this
                }
            } else {
                console.log('⚠️  Submit button not found');
                testsPassed++;
            }
        } catch (error) {
            console.log(`❌ Test 1 failed: ${error.message}`);
            testsFailed++;
        }

        // Test 2: Navigate to non-existent research ID
        console.log('\n📝 Test 2: Non-existent research page');
        try {
            await page.goto(`${BASE_URL}/research/results/nonexistent-id-99999`, {
                waitUntil: 'domcontentloaded',
                timeout: 30000
            });

            // Should show error message or redirect
            const pageContent = await page.content();
            const hasErrorMessage = pageContent.includes('not found') ||
                pageContent.includes('error') ||
                pageContent.includes('Error') ||
                pageContent.includes('404') ||
                page.url().includes('/auth/') ||
                page.url() === `${BASE_URL}/`;

            if (hasErrorMessage) {
                console.log('✅ Invalid research ID handled gracefully');
                testsPassed++;
            } else {
                console.log('⚠️  Page loaded without error indication');
                testsPassed++; // May still be valid behavior
            }
        } catch (error) {
            console.log(`✅ Invalid research ID caused expected error: ${error.message}`);
            testsPassed++; // Error is expected behavior
        }

        // Test 3: Settings page error handling
        console.log('\n📝 Test 3: Settings page loads without JS errors');
        try {
            const preErrorCount = consoleErrors.length;
            await page.goto(`${BASE_URL}/settings/`, { waitUntil: 'domcontentloaded' });

            // Wait for page to stabilize
            await new Promise(resolve => setTimeout(resolve, 2000));

            // Check for critical JS errors (not all errors are bad)
            const newErrors = consoleErrors.slice(preErrorCount);
            const criticalErrors = newErrors.filter(e =>
                e.includes('Uncaught') ||
                e.includes('TypeError') ||
                e.includes('ReferenceError')
            );

            if (criticalErrors.length === 0) {
                console.log('✅ Settings page loads without critical JS errors');
                testsPassed++;
            } else {
                console.log(`⚠️  Settings page has ${criticalErrors.length} critical errors`);
                criticalErrors.forEach(e => console.log(`    - ${e}`));
                testsFailed++;
            }
        } catch (error) {
            console.log(`❌ Test 3 failed: ${error.message}`);
            testsFailed++;
        }

        // Test 4: Metrics page graceful degradation
        console.log('\n📝 Test 4: Metrics page handles no data gracefully');
        try {
            await page.goto(`${BASE_URL}/metrics/`, { waitUntil: 'domcontentloaded' });

            // Page should load even with no metrics data
            const hasMetricsContent = await page.evaluate(() => {
                const body = document.body;
                return body && body.innerText.length > 100;
            });

            if (hasMetricsContent) {
                console.log('✅ Metrics page loads gracefully');
                testsPassed++;
            } else {
                console.log('⚠️  Metrics page appears empty but loaded');
                testsPassed++; // Still valid
            }
        } catch (error) {
            console.log(`❌ Test 4 failed: ${error.message}`);
            testsFailed++;
        }

        // Test 5: History page with no history
        console.log('\n📝 Test 5: History page handles empty history');
        try {
            await page.goto(`${BASE_URL}/history/`, { waitUntil: 'domcontentloaded' });

            // Should show empty state or message
            const pageContent = await page.content();
            const hasContent = pageContent.includes('history') ||
                pageContent.includes('History') ||
                pageContent.includes('research') ||
                pageContent.includes('No ') ||
                pageContent.includes('empty');

            if (hasContent) {
                console.log('✅ History page handles empty state gracefully');
                testsPassed++;
            } else {
                console.log('⚠️  History page content unclear');
                testsPassed++;
            }
        } catch (error) {
            console.log(`❌ Test 5 failed: ${error.message}`);
            testsFailed++;
        }

        // Test 6: API error simulation
        console.log('\n📝 Test 6: UI handles API errors');
        try {
            await page.goto(`${BASE_URL}/`, { waitUntil: 'domcontentloaded' });

            // Monitor for failed requests
            let failedRequests = 0;
            page.on('requestfailed', () => failedRequests++);

            // Try to trigger an API call (visit settings)
            await page.goto(`${BASE_URL}/settings/`, { waitUntil: 'domcontentloaded' });
            await new Promise(resolve => setTimeout(resolve, 2000));

            // Check page is still usable
            const isPageUsable = await page.evaluate(() => {
                return document.body !== null && document.body.innerHTML.length > 0;
            });

            if (isPageUsable) {
                console.log(`✅ UI remains usable (${failedRequests} failed requests handled)`);
                testsPassed++;
            } else {
                console.log('❌ UI became unusable after errors');
                testsFailed++;
            }
        } catch (error) {
            console.log(`❌ Test 6 failed: ${error.message}`);
            testsFailed++;
        }

        // Summary
        console.log('\n' + '='.repeat(50));
        console.log('📊 ERROR RECOVERY TEST SUMMARY');
        console.log('='.repeat(50));
        console.log(`✅ Passed: ${testsPassed}`);
        console.log(`❌ Failed: ${testsFailed}`);
        console.log(`📊 Success Rate: ${Math.round((testsPassed / (testsPassed + testsFailed)) * 100)}%`);

        if (testsFailed > 0) {
            console.log('\n⚠️  Some error recovery tests failed');
            if (!isCI) {
                await page.screenshot({
                    path: path.join(screenshotsDir, 'error_recovery_final.png'),
                    fullPage: true
                });
            }
            process.exit(1);
        }

        console.log('\n🎉 All error recovery tests passed!');
        process.exit(0);

    } catch (error) {
        console.error('\n❌ Test suite failed:', error.message);

        // Skip diagnostic screenshot in CI — error context is in the logs
        if (!isCI) {
            try {
                await page.screenshot({
                    path: path.join(screenshotsDir, `error_recovery_error_${Date.now()}.png`),
                    fullPage: true
                });
                console.log('📸 Error screenshot saved');
            } catch (screenshotError) {
                console.log('Could not save screenshot:', screenshotError.message);
            }
        }

        process.exit(1);
    } finally {
        await browser.close();
    }
}

// Run the test
testErrorRecovery().catch(error => {
    console.error('Fatal error:', error);
    process.exit(1);
});
