/**
 * Security Framework Test Suite
 * 
 * Tests the new security framework implementation:
 * - Role-based access control (trainer, master_trainer, admin)
 * - CSRF protection via nonce verification
 * - Input sanitization validation
 * - Authentication boundary testing
 * - Permission escalation prevention
 * - Session security
 * 
 * @package HVAC_Community_Events
 * @version 3.0.0
 * @created 2025-08-20
 */

const { test, expect, authHelpers, authScenarios } = 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 = 90000;

// Test users with different privilege levels (now handled by auth system)
const USER_ACCESS_MATRIX = {
    trainer: {
        role: 'hvac_trainer',
        expectedPages: ['/trainer/dashboard/', '/trainer/profile/', '/trainer/events/']
    },
    master_trainer: {
        role: 'hvac_master_trainer',
        expectedPages: ['/master-trainer/master-dashboard/', '/trainer/dashboard/', '/trainer/events/']
    },
    admin: {
        role: 'administrator',
        expectedPages: ['/wp-admin/', '/trainer/dashboard/', '/master-trainer/master-dashboard/']
    }
};

// Security test payloads
const SECURITY_PAYLOADS = {
    xss: [
        '<script>alert("xss")</script>',
        '"><script>alert("xss")</script>',
        'javascript:alert("xss")',
        '<img src=x onerror=alert("xss")>',
        '\"><svg onload=alert("xss")>'
    ],
    sqlInjection: [
        "'; DROP TABLE wp_users; --",
        "' OR '1'='1",
        "1' UNION SELECT * FROM wp_users --",
        "'; INSERT INTO wp_users VALUES('test'); --"
    ],
    pathTraversal: [
        '../../../etc/passwd',
        '..\\..\\..\\windows\\system32\\drivers\\etc\\hosts',
        '....//....//....//etc/passwd',
        '/var/www/wp-config.php'
    ],
    commandInjection: [
        '; cat /etc/passwd',
        '| whoami',
        '&& ls -la',
        '`rm -rf /`'
    ]
};

// Helper functions - updated to use new auth system
async function loginAsUser(page, userType = 'trainer') {
    await authHelpers.loginAs(page, userType);
}

async function attemptUnauthorizedAccess(page, url, expectedResult = 'denied') {
    const response = await page.goto(url);
    await page.waitForTimeout(2000);
    
    const statusCode = response?.status() || 0;
    const content = await page.content();
    const currentUrl = page.url();
    
    return {
        statusCode,
        content,
        currentUrl,
        isAccessDenied: content.includes('Access denied') || 
                       content.includes('Insufficient permissions') ||
                       content.includes('403 Forbidden') ||
                       statusCode === 403 ||
                       currentUrl.includes('wp-login.php'),
        isRedirected: currentUrl !== url
    };
}

async function testFormWithPayloads(page, formSelector, fieldMappings, payloads) {
    const results = [];
    
    for (const payload of payloads) {
        try {
            // Fill form with malicious payload
            for (const [fieldSelector, payloadValue] of Object.entries(fieldMappings)) {
                const field = await page.$(fieldSelector);
                if (field) {
                    await field.fill(typeof payloadValue === 'function' ? payloadValue(payload) : payload);
                }
            }
            
            // Submit form
            const submitButton = await page.$(`${formSelector} button[type="submit"], ${formSelector} input[type="submit"]`);
            if (submitButton) {
                await submitButton.click();
                await page.waitForTimeout(2000);
                
                // Check response
                const content = await page.content();
                const hasPayload = content.includes(payload);
                const hasError = content.includes('error') || content.includes('Error');
                
                results.push({
                    payload,
                    reflected: hasPayload,
                    hasError,
                    sanitized: !hasPayload || hasError
                });
            }
        } catch (error) {
            results.push({
                payload,
                reflected: false,
                hasError: true,
                sanitized: true,
                error: error.message
            });
        }
    }
    
    return results;
}

async function extractNonceFields(page) {
    return await page.evaluate(() => {
        const nonceFields = Array.from(document.querySelectorAll('input[name*="nonce"], input[name*="_token"], input[name*="_wpnonce"]'));
        return nonceFields.map(field => ({
            name: field.name,
            value: field.value,
            form: field.closest('form')?.id || 'unknown'
        }));
    });
}

async function takeSecurityScreenshot(page, name) {
    const screenshotDir = path.join(__dirname, '../../screenshots/security');
    await require('fs').promises.mkdir(screenshotDir, { recursive: true });
    await page.screenshot({ 
        path: path.join(screenshotDir, `${name}-${Date.now()}.png`),
        fullPage: true 
    });
}

test.describe('Security Framework Tests', () => {
    test.setTimeout(TEST_TIMEOUT);
    
    test.beforeEach(async ({ page }) => {
        await page.setViewportSize({ width: 1280, height: 720 });
    });

    test.describe('Role-Based Access Control Tests', () => {
        test('should enforce trainer role access restrictions', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            // Test allowed pages
            const allowedPages = USER_ACCESS_MATRIX.trainer.expectedPages;
            for (const allowedPage of allowedPages) {
                const response = await page.goto(`${BASE_URL}${allowedPage}`);
                expect(response?.status()).toBeLessThan(400);
                console.log(`Trainer access to ${allowedPage}: OK`);
            }
            
            // Test restricted pages
            const restrictedPages = [
                '/wp-admin/',
                '/master-trainer/master-dashboard/',
                '/wp-admin/users.php',
                '/wp-admin/plugins.php'
            ];
            
            for (const restrictedPage of restrictedPages) {
                const result = await attemptUnauthorizedAccess(page, `${BASE_URL}${restrictedPage}`);
                
                // Should be denied or redirected
                const isProperlyRestricted = result.isAccessDenied || 
                                          result.statusCode >= 400 || 
                                          result.isRedirected;
                
                expect(isProperlyRestricted).toBeTruthy();
                console.log(`Trainer restriction for ${restrictedPage}:`, isProperlyRestricted ? 'BLOCKED' : 'ALLOWED');
            }
            
            await takeSecurityScreenshot(page, 'trainer-access-control');
        });

        test('should enforce master trainer role privileges', async ({ page }) => {
            try {
                await loginAsUser(page, 'master_trainer');
                
                // Master trainer should access both trainer and master pages
                const allowedPages = [
                    '/trainer/dashboard/',
                    '/master-trainer/master-dashboard/',
                    '/trainer/events/',
                    '/trainer/profile/'
                ];
                
                for (const allowedPage of allowedPages) {
                    const response = await page.goto(`${BASE_URL}${allowedPage}`);
                    expect(response?.status()).toBeLessThan(400);
                    console.log(`Master trainer access to ${allowedPage}: OK`);
                }
                
                // Still should not access admin pages
                const restrictedPages = [
                    '/wp-admin/users.php',
                    '/wp-admin/plugins.php',
                    '/wp-admin/themes.php'
                ];
                
                for (const restrictedPage of restrictedPages) {
                    const result = await attemptUnauthorizedAccess(page, `${BASE_URL}${restrictedPage}`);
                    
                    const isProperlyRestricted = result.isAccessDenied || 
                                              result.statusCode >= 400 || 
                                              result.isRedirected;
                    
                    // Note: Master trainers might have some admin access
                    console.log(`Master trainer restriction for ${restrictedPage}:`, isProperlyRestricted ? 'BLOCKED' : 'ALLOWED');
                }
                
            } catch (error) {
                console.log('Master trainer test skipped - user may not exist:', error.message);
            }
        });

        test('should prevent privilege escalation attempts', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            // Attempt to modify user role via form manipulation
            await page.goto(`${BASE_URL}/trainer/profile/edit/`);
            
            // Try to inject role escalation parameters
            const escalationAttempts = [
                { field: 'role', value: 'administrator' },
                { field: 'wp_capabilities', value: 'administrator' },
                { field: 'user_role', value: 'hvac_master_trainer' }
            ];
            
            for (const attempt of escalationAttempts) {
                try {
                    // Inject hidden field via JavaScript
                    await page.evaluate((field, value) => {
                        const form = document.querySelector('form');
                        if (form) {
                            const input = document.createElement('input');
                            input.type = 'hidden';
                            input.name = field;
                            input.value = value;
                            form.appendChild(input);
                        }
                    }, attempt.field, attempt.value);
                    
                    console.log(`Injected privilege escalation attempt: ${attempt.field} = ${attempt.value}`);
                } catch (error) {
                    console.log(`Failed to inject ${attempt.field}:`, error.message);
                }
            }
            
            // Submit form and check if escalation was prevented
            const submitButton = await page.$('button[type="submit"], input[type="submit"]');
            if (submitButton) {
                await submitButton.click();
                await page.waitForTimeout(3000);
                
                // User should still be trainer role
                await page.goto(`${BASE_URL}/master-trainer/master-dashboard/`);
                const result = await attemptUnauthorizedAccess(page, `${BASE_URL}/master-trainer/master-dashboard/`);
                
                expect(result.isAccessDenied || result.isRedirected).toBeTruthy();
            }
        });

        test('should validate session security', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            // Check for secure session cookies
            const cookies = await page.context().cookies();
            const sessionCookie = cookies.find(c => c.name.includes('session') || c.name.includes('wordpress'));
            
            if (sessionCookie) {
                expect(sessionCookie.httpOnly).toBeTruthy();
                // Note: Secure flag may not be set in development
                console.log('Session cookie security:', {
                    httpOnly: sessionCookie.httpOnly,
                    secure: sessionCookie.secure
                });
            }
            
            // Test session timeout
            await page.goto(`${BASE_URL}/trainer/dashboard/`);
            
            // Simulate session manipulation
            await page.evaluate(() => {
                // Try to access session storage
                try {
                    sessionStorage.setItem('test_key', 'test_value');
                    localStorage.setItem('test_key', 'test_value');
                } catch (e) {
                    console.log('Storage access restricted:', e.message);
                }
            });
        });
    });

    test.describe('CSRF Protection Tests', () => {
        test('should include nonce fields in forms', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            const formsToCheck = [
                '/trainer/profile/edit/',
                '/trainer/events/create/',
                '/trainer/organizer/manage/'
            ];
            
            for (const formPage of formsToCheck) {
                await page.goto(`${BASE_URL}${formPage}`);
                await page.waitForTimeout(2000);
                
                const nonceFields = await extractNonceFields(page);
                
                expect(nonceFields.length).toBeGreaterThan(0);
                console.log(`Nonce fields found on ${formPage}:`, nonceFields.length);
                
                // Verify nonce values are not empty
                nonceFields.forEach(field => {
                    expect(field.value).toBeTruthy();
                    expect(field.value.length).toBeGreaterThan(5);
                });
            }
        });

        test('should reject forms without valid nonces', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/profile/edit/`);
            
            // Remove or modify nonce fields
            await page.evaluate(() => {
                const nonceFields = document.querySelectorAll('input[name*="nonce"]');
                nonceFields.forEach(field => {
                    field.value = 'invalid_nonce_value';
                });
            });
            
            // Try to submit form
            const submitButton = await page.$('button[type="submit"], input[type="submit"]');
            if (submitButton) {
                await submitButton.click();
                await page.waitForTimeout(3000);
                
                // Should show error or reject submission
                const content = await page.content();
                const hasError = content.includes('error') || 
                               content.includes('Error') ||
                               content.includes('nonce') ||
                               content.includes('Security check failed');
                
                console.log('Invalid nonce rejection:', hasError ? 'BLOCKED' : 'ALLOWED');
                // Note: Some forms might not validate nonces in development
            }
        });

        test('should prevent CSRF attacks via external submission', async ({ page, context }) => {
            await loginAsUser(page, 'trainer');
            
            // Get a legitimate form's nonce
            await page.goto(`${BASE_URL}/trainer/profile/edit/`);
            const legitimateNonce = await page.evaluate(() => {
                const nonceField = document.querySelector('input[name*="nonce"]');
                return nonceField ? nonceField.value : null;
            });
            
            // Create new context (simulating external site)
            const externalContext = await page.context().browser().newContext();
            const externalPage = await externalContext.newPage();
            
            // Try to submit form from external context using stolen nonce
            const formData = new URLSearchParams({
                'user_email': 'hacker@evil.com',
                'nonce': legitimateNonce || 'fake_nonce'
            });
            
            try {
                const response = await externalPage.request.post(`${BASE_URL}/trainer/profile/edit/`, {
                    data: formData.toString(),
                    headers: {
                        'Content-Type': 'application/x-www-form-urlencoded'
                    }
                });
                
                // Should be rejected (403/405 or redirect)
                const isBlocked = response.status() >= 400 || 
                                response.headers()['location']?.includes('login');
                
                expect(isBlocked).toBeTruthy();
                console.log('External CSRF attempt blocked:', isBlocked);
                
            } catch (error) {
                console.log('CSRF attempt failed (good):', error.message);
            }
            
            await externalContext.close();
        });
    });

    test.describe('Input Sanitization Tests', () => {
        test('should sanitize XSS payloads in event creation', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Wait for form to load
            await page.waitForSelector('.hvac-event-form-wrapper, iframe#tec-create-frame', { timeout: 10000 });
            
            const iframe = await page.$('iframe#tec-create-frame');
            const context = iframe ? await iframe.contentFrame() : page;
            
            const fieldMappings = {
                'input[name="post_title"], #tribe-events-title': (payload) => `XSS Test ${payload}`,
                '#content, textarea[name="post_content"]': (payload) => `Description ${payload}`,
                'input[name="venue[Venue]"], #venue-name': (payload) => `Venue ${payload}`
            };
            
            const results = await testFormWithPayloads(context, 'form', fieldMappings, SECURITY_PAYLOADS.xss);
            
            // All XSS payloads should be sanitized
            results.forEach(result => {
                expect(result.sanitized).toBeTruthy();
                console.log(`XSS payload "${result.payload}" sanitized:`, result.sanitized);
            });
            
            await takeSecurityScreenshot(page, 'xss-sanitization-test');
        });

        test('should handle SQL injection attempts safely', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/profile/edit/`);
            
            const sqlPayloads = SECURITY_PAYLOADS.sqlInjection;
            
            for (const payload of sqlPayloads) {
                // Try SQL injection in various fields
                const emailField = await page.$('input[type="email"], input[name="email"]');
                if (emailField) {
                    await emailField.fill(`test${payload}@example.com`);
                }
                
                const nameField = await page.$('input[name="first_name"], input[name="display_name"]');
                if (nameField) {
                    await nameField.fill(`Test${payload}`);
                }
                
                // Submit and check for errors
                const submitButton = await page.$('button[type="submit"], input[type="submit"]');
                if (submitButton) {
                    await submitButton.click();
                    await page.waitForTimeout(2000);
                    
                    const content = await page.content();
                    const hasSqlError = content.includes('SQL') || 
                                      content.includes('mysql') ||
                                      content.includes('database error');
                    
                    // Should not expose SQL errors
                    expect(hasSqlError).toBeFalsy();
                    console.log(`SQL injection payload "${payload}" handled safely`);
                }
                
                // Reset form for next test
                await page.reload();
                await page.waitForTimeout(1000);
            }
        });

        test('should prevent path traversal attacks', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            const pathPayloads = SECURITY_PAYLOADS.pathTraversal;
            
            for (const payload of pathPayloads) {
                // Test path traversal in file upload fields
                await page.goto(`${BASE_URL}/trainer/profile/edit/`);
                
                const fileInput = await page.$('input[type="file"]');
                if (fileInput) {
                    try {
                        // Create temporary file with malicious name
                        const fs = require('fs');
                        const tmpPath = path.join(__dirname, 'temp_test_file.txt');
                        fs.writeFileSync(tmpPath, 'test content');
                        
                        await fileInput.setInputFiles(tmpPath);
                        
                        const submitButton = await page.$('button[type="submit"], input[type="submit"]');
                        if (submitButton) {
                            await submitButton.click();
                            await page.waitForTimeout(3000);
                            
                            // Check if file was processed safely
                            const content = await page.content();
                            const hasTraversalContent = content.includes('/etc/passwd') ||
                                                      content.includes('windows/system32');
                            
                            expect(hasTraversalContent).toBeFalsy();
                            console.log(`Path traversal payload "${payload}" blocked`);
                        }
                        
                        // Cleanup
                        if (fs.existsSync(tmpPath)) {
                            fs.unlinkSync(tmpPath);
                        }
                        
                    } catch (error) {
                        console.log(`Path traversal test for "${payload}" failed safely:`, error.message);
                    }
                }
            }
        });

        test('should escape output in templates', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            // Test output escaping in various templates
            const pagesToCheck = [
                '/trainer/dashboard/',
                '/trainer/profile/',
                '/trainer/events/'
            ];
            
            for (const pagePath of pagesToCheck) {
                await page.goto(`${BASE_URL}${pagePath}`);
                
                // Check for unescaped content patterns
                const unsafePatterns = await page.evaluate(() => {
                    const content = document.body.innerHTML;
                    const patterns = [
                        /<script[^>]*>[^<]*<\/script>/gi,
                        /javascript:[^"'>\s]*/gi,
                        /on\w+\s*=\s*[^>]*/gi
                    ];
                    
                    return patterns.map(pattern => ({
                        pattern: pattern.toString(),
                        matches: content.match(pattern) || []
                    }));
                });
                
                unsafePatterns.forEach(result => {
                    if (result.matches.length > 0) {
                        console.log(`Potentially unsafe content on ${pagePath}:`, result.matches);
                    }
                });
            }
        });
    });

    test.describe('Authentication Security Tests', () => {
        test('should enforce strong password requirements', async ({ page }) => {
            await page.goto(`${BASE_URL}/wp-login.php?action=register`);
            
            // If registration is available, test password requirements
            const registerForm = await page.$('#registerform, .register-form');
            if (registerForm) {
                const weakPasswords = [
                    '123456',
                    'password',
                    'abc123',
                    '1234',
                    'test'
                ];
                
                for (const weakPassword of weakPasswords) {
                    await page.fill('#user_pass, input[name="pass1"]', weakPassword);
                    
                    // Check for password strength indicator
                    await page.waitForTimeout(500);
                    
                    const strengthIndicator = await page.evaluate(() => {
                        const indicator = document.querySelector('.password-strength, #pass-strength-result');
                        return indicator ? indicator.textContent : '';
                    });
                    
                    console.log(`Password "${weakPassword}" strength:`, strengthIndicator);
                }
            } else {
                console.log('Registration form not available for testing');
            }
        });

        test('should implement account lockout after failed attempts', async ({ page }) => {
            // Test with intentionally wrong credentials
            const fakeUser = {
                email: 'nonexistent@example.com',
                password: 'WrongPassword123!'
            };
            
            for (let attempt = 1; attempt <= 5; attempt++) {
                await page.goto(`${BASE_URL}/wp-login.php`);
                await page.fill('#user_login', fakeUser.email);
                await page.fill('#user_pass', fakeUser.password);
                await page.click('#wp-submit');
                
                await page.waitForTimeout(1000);
                
                const errorMessage = await page.evaluate(() => {
                    const error = document.querySelector('#login_error, .login-error');
                    return error ? error.textContent : '';
                });
                
                console.log(`Failed login attempt ${attempt}:`, errorMessage);
                
                // Check if account gets locked after multiple attempts
                if (attempt >= 3 && errorMessage.includes('locked')) {
                    console.log('Account lockout mechanism detected');
                    break;
                }
            }
        });

        test('should secure password reset process', async ({ page }) => {
            await page.goto(`${BASE_URL}/wp-login.php?action=lostpassword`);
            
            const resetForm = await page.$('#lostpasswordform');
            if (resetForm) {
                // Test with valid email
                await page.fill('#user_login', 'test_trainer@example.com');
                await page.click('#wp-submit');
                
                await page.waitForTimeout(2000);
                
                const message = await page.evaluate(() => {
                    return document.body.textContent;
                });
                
                // Should not reveal whether email exists
                const isSecure = !message.includes('does not exist') &&
                               !message.includes('not found') &&
                               message.includes('sent') || message.includes('check');
                
                expect(isSecure).toBeTruthy();
                console.log('Password reset process secure:', isSecure);
            }
        });

        test('should validate session hijacking protection', async ({ browser }) => {
            // Create two contexts to simulate session hijacking
            const context1 = await browser.newContext();
            const context2 = await browser.newContext();
            
            const page1 = await context1.newPage();
            const page2 = await context2.newPage();
            
            // Login in first context
            await loginAsUser(page1, 'trainer');
            
            // Get session cookies from first context
            const cookies = await context1.cookies();
            const sessionCookies = cookies.filter(c => 
                c.name.includes('wordpress') || c.name.includes('session')
            );
            
            // Try to use session cookies in second context
            if (sessionCookies.length > 0) {
                await context2.addCookies(sessionCookies);
                
                // Try to access protected page in second context
                await page2.goto(`${BASE_URL}/trainer/dashboard/`);
                const isRedirected = page2.url().includes('wp-login.php');
                
                console.log('Session hijacking protection:', isRedirected ? 'ACTIVE' : 'WEAK');
            }
            
            await context1.close();
            await context2.close();
        });
    });
});

// Export security test configuration
module.exports = {
    testDir: __dirname,
    timeout: TEST_TIMEOUT,
    retries: 1,
    workers: 1, // Sequential for security tests
    use: {
        baseURL: BASE_URL,
        screenshot: 'only-on-failure',
        video: 'retain-on-failure',
        trace: 'on-first-retry',
        ignoreHTTPSErrors: true // For testing purposes
    }
};