/**
 * Stability & Regression Test Suite
 * 
 * Tests for preventing regressions after major architectural refactoring:
 * - PHP segfault prevention (monitoring disabled areas)
 * - Long-running operation stability
 * - Memory leak detection  
 * - Browser crash prevention (especially Safari)
 * - Background job stability
 * - Resource exhaustion protection
 * - Error recovery mechanisms
 * 
 * @package HVAC_Community_Events
 * @version 3.0.0
 * @created 2025-08-20
 */

const { test, expect, authHelpers } = require('../helpers/auth-fixtures');
const path = require('path');

// Test configuration
const BASE_URL = process.env.UPSKILL_STAGING_URL || 'https://upskill-staging.measurequick.com';
const TEST_TIMEOUT = 180000; // Extended for stability tests

// Stability test scenarios
const STRESS_TEST_SCENARIOS = {
    rapidNavigation: {
        pages: ['/trainer/dashboard/', '/trainer/events/', '/trainer/profile/', '/trainer/certificate-reports/'],
        iterations: 10,
        delay: 500
    },
    formSubmission: {
        forms: ['/trainer/profile/edit/', '/trainer/events/create/'],
        iterations: 5,
        delay: 1000
    },
    resourceLoading: {
        pages: ['/find-trainer/', '/trainer/dashboard/'],
        iterations: 8,
        delay: 2000
    }
};

// Memory thresholds
const MEMORY_LIMITS = {
    maxHeapSize: 150, // MB
    maxHeapGrowth: 50, // MB per operation
    maxLeakRate: 10   // MB per minute
};

// Helper functions
async function loginAsTrainer(page) {
    await authHelpers.loginAs(page, 'trainer');
}

async function monitorMemoryUsage(page) {
    return await page.evaluate(() => {
        if (performance.memory) {
            return {
                used: performance.memory.usedJSHeapSize / 1024 / 1024, // MB
                total: performance.memory.totalJSHeapSize / 1024 / 1024, // MB
                limit: performance.memory.jsHeapSizeLimit / 1024 / 1024, // MB
                timestamp: Date.now()
            };
        }
        return null;
    });
}

async function forceGarbageCollection(page) {
    await page.evaluate(() => {
        if (window.gc) {
            window.gc();
        }
        
        // Force some cleanup
        if (window.performance && window.performance.clearResourceTimings) {
            window.performance.clearResourceTimings();
        }
    });
}

async function detectPageErrors(page) {
    return await page.evaluate(() => {
        const errors = [];
        
        // Check for JavaScript errors in console
        if (window.console && window.console.logs) {
            errors.push(...window.console.logs.filter(log => 
                log.includes('error') || log.includes('Error')
            ));
        }
        
        // Check for PHP errors in page content
        const content = document.body.textContent;
        const phpErrors = [
            'Fatal error:',
            'Parse error:',
            'Warning:',
            'Notice:',
            'Deprecated:',
            'Catchable fatal error:',
            'segmentation fault'
        ];
        
        phpErrors.forEach(errorType => {
            if (content.includes(errorType)) {
                errors.push(`PHP Error: ${errorType}`);
            }
        });
        
        // Check for broken images/resources
        const brokenImages = Array.from(document.querySelectorAll('img')).filter(img => 
            !img.complete || img.naturalHeight === 0
        );
        
        if (brokenImages.length > 0) {
            errors.push(`${brokenImages.length} broken images`);
        }
        
        return errors;
    });
}

async function stressTestNavigation(page, scenario) {
    const results = {
        iterations: 0,
        errors: [],
        loadTimes: [],
        memoryUsage: []
    };
    
    for (let i = 0; i < scenario.iterations; i++) {
        for (const pagePath of scenario.pages) {
            const startTime = Date.now();
            
            try {
                await page.goto(`${BASE_URL}${pagePath}`, { 
                    waitUntil: 'domcontentloaded',
                    timeout: 15000 
                });
                
                const loadTime = Date.now() - startTime;
                results.loadTimes.push(loadTime);
                
                // Check for errors
                const pageErrors = await detectPageErrors(page);
                results.errors.push(...pageErrors);
                
                // Monitor memory
                const memory = await monitorMemoryUsage(page);
                if (memory) {
                    results.memoryUsage.push(memory);
                }
                
                // Brief pause
                await page.waitForTimeout(scenario.delay);
                
            } catch (error) {
                results.errors.push(`Navigation error: ${error.message}`);
            }
        }
        
        results.iterations = i + 1;
        
        // Force cleanup every few iterations
        if (i % 3 === 0) {
            await forceGarbageCollection(page);
        }
    }
    
    return results;
}

async function stressTestForms(page, scenario) {
    const results = {
        iterations: 0,
        errors: [],
        submissionTimes: [],
        memoryUsage: []
    };
    
    for (let i = 0; i < scenario.iterations; i++) {
        for (const formPath of scenario.forms) {
            try {
                await page.goto(`${BASE_URL}${formPath}`);
                await page.waitForSelector('form', { timeout: 10000 });
                
                // Fill form with test data
                const startTime = Date.now();
                
                const textInputs = await page.$$('input[type="text"], input[type="email"], textarea');
                for (const input of textInputs.slice(0, 3)) { // Limit to first 3 inputs
                    await input.fill(`Test data ${Date.now()}`);
                }
                
                // Submit if possible
                const submitButton = await page.$('button[type="submit"], input[type="submit"]');
                if (submitButton) {
                    await submitButton.click();
                    await page.waitForTimeout(2000);
                }
                
                const submissionTime = Date.now() - startTime;
                results.submissionTimes.push(submissionTime);
                
                // Check for errors
                const pageErrors = await detectPageErrors(page);
                results.errors.push(...pageErrors);
                
                // Monitor memory
                const memory = await monitorMemoryUsage(page);
                if (memory) {
                    results.memoryUsage.push(memory);
                }
                
                await page.waitForTimeout(scenario.delay);
                
            } catch (error) {
                results.errors.push(`Form error: ${error.message}`);
            }
        }
        
        results.iterations = i + 1;
        
        if (i % 2 === 0) {
            await forceGarbageCollection(page);
        }
    }
    
    return results;
}

async function takeStabilityScreenshot(page, name, metrics) {
    const screenshotDir = path.join(__dirname, '../../screenshots/stability');
    await require('fs').promises.mkdir(screenshotDir, { recursive: true });
    
    await page.screenshot({ 
        path: path.join(screenshotDir, `${name}-${Date.now()}.png`),
        fullPage: true 
    });
    
    // Log metrics for debugging
    console.log(`Stability metrics for ${name}:`, metrics);
}

test.describe('Stability & Regression Tests', () => {
    test.setTimeout(TEST_TIMEOUT);
    
    test.beforeEach(async ({ page }) => {
        await page.setViewportSize({ width: 1280, height: 720 });
        
        // Set up error monitoring
        page.on('pageerror', error => {
            console.log('Page error detected:', error.message);
        });
        
        page.on('requestfailed', request => {
            console.log('Request failed:', request.url(), request.failure()?.errorText);
        });
        
        // Login before each test to ensure authenticated access
        await authHelpers.loginAs(page, 'trainer');
    });

    test.describe('PHP Segfault Prevention Tests', () => {
        test('should not trigger segfaults with monitoring systems disabled', async ({ page }) => {
            
            // Test operations that previously caused segfaults
            const riskOperations = [
                async () => {
                    await page.goto(`${BASE_URL}/trainer/dashboard/`);
                    await page.waitForLoadState('domcontentloaded');
                },
                async () => {
                    await page.goto(`${BASE_URL}/trainer/events/create/`);
                    await page.waitForSelector('form, iframe', { timeout: 10000 });
                },
                async () => {
                    await page.goto(`${BASE_URL}/find-trainer/`);
                    await page.waitForLoadState('networkidle', { timeout: 30000 });
                },
                async () => {
                    // Heavy form interaction
                    await page.goto(`${BASE_URL}/trainer/profile/edit/`);
                    const inputs = await page.$$('input, select, textarea');
                    for (const input of inputs.slice(0, 5)) {
                        await input.fill('Test data');
                    }
                }
            ];
            
            for (let i = 0; i < riskOperations.length; i++) {
                const operation = riskOperations[i];
                
                try {
                    await operation();
                    
                    // Check for segfault indicators
                    const errors = await detectPageErrors(page);
                    const hasSegfault = errors.some(error => 
                        error.includes('segmentation fault') ||
                        error.includes('Fatal error') ||
                        error.includes('Process terminated')
                    );
                    
                    expect(hasSegfault).toBeFalsy();
                    console.log(`Risk operation ${i + 1} completed safely`);
                    
                } catch (error) {
                    // Should not crash the test
                    console.log(`Risk operation ${i + 1} error:`, error.message);
                    expect(error.message).not.toContain('segmentation fault');
                }
                
                await page.waitForTimeout(2000);
            }
        });

        test('should handle resource-intensive operations safely', async ({ page }) => {
            
            // Simulate resource-intensive operations
            const heavyOperations = [
                {
                    name: 'Multiple simultaneous AJAX requests',
                    operation: async () => {
                        await page.goto(`${BASE_URL}/trainer/dashboard/`);
                        
                        // Trigger multiple requests
                        await page.evaluate(() => {
                            for (let i = 0; i < 5; i++) {
                                fetch(window.location.href + '?test=' + i);
                            }
                        });
                    }
                },
                {
                    name: 'Large form data processing',
                    operation: async () => {
                        await page.goto(`${BASE_URL}/trainer/profile/edit/`);
                        
                        // Fill form with large amounts of data
                        const largeText = 'Lorem ipsum dolor sit amet, '.repeat(100);
                        const textareas = await page.$$('textarea');
                        for (const textarea of textareas.slice(0, 2)) {
                            await textarea.fill(largeText);
                        }
                    }
                },
                {
                    name: 'Rapid page transitions',
                    operation: async () => {
                        const pages = ['/trainer/dashboard/', '/trainer/events/', '/trainer/profile/'];
                        for (const pagePath of pages) {
                            await page.goto(`${BASE_URL}${pagePath}`, { 
                                waitUntil: 'domcontentloaded',
                                timeout: 10000 
                            });
                            await page.waitForTimeout(100); // Minimal delay
                        }
                    }
                }
            ];
            
            for (const operation of heavyOperations) {
                try {
                    await operation.operation();
                    
                    // Check system stability
                    const isStable = await page.evaluate(() => {
                        return document.readyState === 'complete' && 
                               !document.body.textContent.includes('Fatal error');
                    });
                    
                    expect(isStable).toBeTruthy();
                    console.log(`Heavy operation "${operation.name}" completed safely`);
                    
                } catch (error) {
                    console.log(`Heavy operation "${operation.name}" error:`, error.message);
                    expect(error.message).not.toContain('timeout');
                }
                
                await page.waitForTimeout(3000);
            }
        });
    });

    test.describe('Memory Leak Detection Tests', () => {
        test('should not leak memory during normal operations', async ({ page, browserName }) => {
            test.skip(browserName !== 'chromium', 'Memory monitoring requires Chromium');
            
            
            const memorySnapshots = [];
            const operations = [
                () => page.goto(`${BASE_URL}/trainer/dashboard/`),
                () => page.goto(`${BASE_URL}/trainer/events/`),
                () => page.goto(`${BASE_URL}/trainer/profile/`),
                () => page.goto(`${BASE_URL}/trainer/certificate-reports/`)
            ];
            
            // Baseline memory
            await forceGarbageCollection(page);
            const baselineMemory = await monitorMemoryUsage(page);
            memorySnapshots.push({ operation: 'baseline', ...baselineMemory });
            
            // Perform operations and measure memory
            for (let i = 0; i < operations.length; i++) {
                await operations[i]();
                await page.waitForLoadState('domcontentloaded');
                
                // Force cleanup and measure
                await forceGarbageCollection(page);
                await page.waitForTimeout(1000);
                
                const memory = await monitorMemoryUsage(page);
                if (memory) {
                    memorySnapshots.push({ 
                        operation: `operation_${i}`, 
                        ...memory 
                    });
                }
            }
            
            // Analyze memory growth
            if (memorySnapshots.length > 1) {
                const initialMemory = memorySnapshots[0].used;
                const finalMemory = memorySnapshots[memorySnapshots.length - 1].used;
                const memoryGrowth = finalMemory - initialMemory;
                
                console.log('Memory usage progression:', memorySnapshots.map(s => ({
                    operation: s.operation,
                    used: `${s.used.toFixed(2)}MB`
                })));
                
                // Memory growth should be reasonable
                expect(memoryGrowth).toBeLessThan(MEMORY_LIMITS.maxHeapGrowth);
                expect(finalMemory).toBeLessThan(MEMORY_LIMITS.maxHeapSize);
            }
        });

        test('should handle memory pressure gracefully', async ({ page, browserName }) => {
            test.skip(browserName !== 'chromium', 'Memory testing requires Chromium');
            
            
            // Create memory pressure
            await page.evaluate(() => {
                // Create some memory pressure (but not enough to crash)
                const arrays = [];
                for (let i = 0; i < 100; i++) {
                    arrays.push(new Array(10000).fill(Math.random()));
                }
                window.memoryPressureArrays = arrays;
            });
            
            const pressuredMemory = await monitorMemoryUsage(page);
            
            // Perform normal operations under memory pressure
            await page.goto(`${BASE_URL}/trainer/dashboard/`);
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Check if operations still work
            const stillFunctional = await page.evaluate(() => {
                return document.readyState === 'complete' &&
                       document.body.textContent.length > 0;
            });
            
            expect(stillFunctional).toBeTruthy();
            
            // Cleanup
            await page.evaluate(() => {
                delete window.memoryPressureArrays;
            });
            
            await forceGarbageCollection(page);
            
            const cleanedMemory = await monitorMemoryUsage(page);
            console.log('Memory under pressure:', {
                baseline: pressuredMemory?.used.toFixed(2) + 'MB',
                cleaned: cleanedMemory?.used.toFixed(2) + 'MB'
            });
        });
    });

    test.describe('Browser Crash Prevention Tests', () => {
        test('should prevent Safari crashes with resource loading', async ({ page, browserName }) => {
            test.skip(browserName !== 'webkit', 'Safari-specific test');
            
            // Extended timeout for Safari
            test.setTimeout(240000);
            
            try {
                // Test the previously problematic find-trainer page
                await page.goto(`${BASE_URL}/find-trainer/`, { 
                    waitUntil: 'networkidle',
                    timeout: 60000 
                });
                
                // Verify page loaded completely
                const pageState = await page.evaluate(() => ({
                    readyState: document.readyState,
                    hasContent: document.body.textContent.length > 100,
                    hasMap: !!document.querySelector('[class*="map"], #map, .mapgeo'),
                    hasTrainerCards: document.querySelectorAll('.trainer-card, .hvac-trainer').length
                }));
                
                expect(pageState.readyState).toBe('complete');
                expect(pageState.hasContent).toBeTruthy();
                
                console.log('Safari page load successful:', pageState);
                
                // Test interaction without crashing
                const interactiveElements = await page.$$('button, a, input');
                if (interactiveElements.length > 0) {
                    await interactiveElements[0].click();
                    await page.waitForTimeout(2000);
                }
                
                await takeStabilityScreenshot(page, 'safari-stability', pageState);
                
            } catch (error) {
                console.error('Safari test failed:', error);
                
                // Take screenshot for debugging
                await page.screenshot({ 
                    path: path.join(__dirname, '../../screenshots/safari-crash-debug.png'),
                    fullPage: true 
                });
                
                // Re-throw if it's a crash, but allow timeouts
                if (!error.message.includes('timeout')) {
                    throw error;
                }
            }
        });

        test('should handle resource loading cascade issues', async ({ page }) => {
            
            // Monitor resource loading
            const resourcePromises = [];
            page.on('response', response => {
                if (response.url().includes('.css') || response.url().includes('.js')) {
                    resourcePromises.push({
                        url: response.url(),
                        status: response.status(),
                        timing: Date.now()
                    });
                }
            });
            
            await page.goto(`${BASE_URL}/trainer/dashboard/`);
            await page.waitForLoadState('networkidle');
            
            // Analyze resource loading pattern
            const cssResources = resourcePromises.filter(r => r.url.includes('.css'));
            const failedResources = resourcePromises.filter(r => r.status >= 400);
            
            console.log('Resource loading analysis:', {
                totalResources: resourcePromises.length,
                cssFiles: cssResources.length,
                failedResources: failedResources.length
            });
            
            // Should not have excessive CSS files (consolidated)
            expect(cssResources.length).toBeLessThan(10);
            
            // Should not have many failed resources
            expect(failedResources.length).toBeLessThan(3);
            
            if (failedResources.length > 0) {
                console.log('Failed resources:', failedResources.map(r => r.url));
            }
        });
    });

    test.describe('Long-Running Operation Tests', () => {
        test('should handle extended user sessions', async ({ page }) => {
            
            const sessionResults = await stressTestNavigation(page, STRESS_TEST_SCENARIOS.rapidNavigation);
            
            // Analyze session stability
            console.log('Extended session results:', {
                iterations: sessionResults.iterations,
                errors: sessionResults.errors.length,
                avgLoadTime: sessionResults.loadTimes.reduce((a, b) => a + b, 0) / sessionResults.loadTimes.length,
                memoryTrend: sessionResults.memoryUsage.length > 0 ? 
                    sessionResults.memoryUsage[sessionResults.memoryUsage.length - 1].used - sessionResults.memoryUsage[0].used : 0
            });
            
            // Should complete most iterations without major errors
            expect(sessionResults.iterations).toBe(STRESS_TEST_SCENARIOS.rapidNavigation.iterations);
            
            // Should not have critical errors
            const criticalErrors = sessionResults.errors.filter(error => 
                error.includes('Fatal') || error.includes('segmentation')
            );
            expect(criticalErrors.length).toBe(0);
            
            // Load times should remain reasonable
            const averageLoadTime = sessionResults.loadTimes.reduce((a, b) => a + b, 0) / sessionResults.loadTimes.length;
            expect(averageLoadTime).toBeLessThan(5000); // 5 seconds max average
            
            await takeStabilityScreenshot(page, 'extended-session', sessionResults);
        });

        test('should handle concurrent user simulation', async ({ browser }) => {
            const concurrentUsers = 3;
            const contexts = await Promise.all(
                Array(concurrentUsers).fill().map(() => browser.newContext())
            );
            
            const userPromises = contexts.map(async (context, index) => {
                const page = await context.newPage();
                
                try {
                            
                    // Simulate different user behaviors
                    const behavior = index % 2 === 0 ? 'navigator' : 'form_user';
                    
                    if (behavior === 'navigator') {
                        return await stressTestNavigation(page, {
                            pages: ['/trainer/dashboard/', '/trainer/events/', '/trainer/profile/'],
                            iterations: 3,
                            delay: 1000
                        });
                    } else {
                        return await stressTestForms(page, {
                            forms: ['/trainer/profile/edit/'],
                            iterations: 2,
                            delay: 2000
                        });
                    }
                } catch (error) {
                    return { error: error.message };
                }
            });
            
            const results = await Promise.all(userPromises);
            
            // Analyze concurrent usage results
            const successfulUsers = results.filter(r => !r.error);
            const errorCounts = results.map(r => r.errors?.length || 0);
            
            console.log('Concurrent users results:', {
                successfulUsers: successfulUsers.length,
                totalErrors: errorCounts.reduce((a, b) => a + b, 0)
            });
            
            // Most users should succeed
            expect(successfulUsers.length).toBeGreaterThanOrEqual(concurrentUsers - 1);
            
            // Total errors should be manageable
            const totalErrors = errorCounts.reduce((a, b) => a + b, 0);
            expect(totalErrors).toBeLessThan(10);
            
            // Cleanup
            await Promise.all(contexts.map(ctx => ctx.close()));
        });

        test('should recover from temporary failures', async ({ page }) => {
            
            // Simulate temporary failures and recovery
            const recoveryTests = [
                {
                    name: 'Network interruption simulation',
                    test: async () => {
                        // Simulate network issues
                        await page.route('**/*', route => {
                            if (Math.random() < 0.1) { // 10% failure rate
                                route.abort();
                            } else {
                                route.continue();
                            }
                        });
                        
                        await page.goto(`${BASE_URL}/trainer/dashboard/`);
                        await page.waitForTimeout(3000);
                        
                        // Remove route handler (recovery)
                        await page.unroute('**/*');
                        
                        // Try normal operation
                        await page.goto(`${BASE_URL}/trainer/profile/`);
                        
                        return await page.locator('body').isVisible();
                    }
                },
                {
                    name: 'Resource timeout recovery',
                    test: async () => {
                        // Add timeout to slow resources
                        await page.route('**/*.css', route => {
                            setTimeout(() => route.continue(), 2000);
                        });
                        
                        await page.goto(`${BASE_URL}/trainer/events/`, { timeout: 30000 });
                        
                        // Remove handler
                        await page.unroute('**/*.css');
                        
                        return await page.locator('body').isVisible();
                    }
                }
            ];
            
            for (const recoveryTest of recoveryTests) {
                try {
                    const recovered = await recoveryTest.test();
                    expect(recovered).toBeTruthy();
                    console.log(`Recovery test "${recoveryTest.name}": PASSED`);
                } catch (error) {
                    console.log(`Recovery test "${recoveryTest.name}": FAILED -`, error.message);
                    // Allow some failures in recovery tests
                }
                
                await page.waitForTimeout(2000);
            }
        });
    });
});

// Export stability test configuration
module.exports = {
    testDir: __dirname,
    timeout: TEST_TIMEOUT,
    retries: 2, // Allow retries for stability tests
    workers: 1, // Sequential to avoid interference
    use: {
        baseURL: BASE_URL,
        screenshot: 'only-on-failure',
        video: 'retain-on-failure',
        trace: 'on-first-retry'
    }
};