/**
 * HVAC Testing Framework - Secure Browser Management
 * 
 * Provides secure browser configuration with hardened security settings,
 * SSL/TLS validation, and secure authentication handling for Playwright.
 * 
 * Security Features:
 * - Hardened browser security configuration
 * - SSL/TLS certificate validation
 * - Secure authentication and session management
 * - Network request filtering and monitoring
 * - Screenshot and trace security controls
 * 
 * @author Claude Code - Emergency Security Response
 * @version 1.0.0
 * @security CRITICAL - Provides secure browser automation
 */

const { chromium, firefox, webkit } = require('playwright');
const fs = require('fs').promises;
const path = require('path');
const { getCredentialManager } = require('./SecureCredentialManager');

class SecureBrowserManager {
    constructor() {
        this.credentialManager = getCredentialManager();
        this.activeBrowsers = new Map();
        this.activeContexts = new Map();
        this.securityConfig = this.loadSecurityConfiguration();
    }

    /**
     * Load security configuration from environment
     * @returns {Object} Security configuration
     */
    loadSecurityConfiguration() {
        return {
            // Browser security settings
            headless: process.env.PLAYWRIGHT_HEADLESS !== 'false',
            slowMo: parseInt(process.env.PLAYWRIGHT_SLOW_MO) || 0,
            timeout: parseInt(process.env.PLAYWRIGHT_TIMEOUT) || 30000,
            
            // SSL/TLS settings
            tlsValidationMode: process.env.TLS_VALIDATION_MODE || 'strict',
            ignoreCertificateErrors: process.env.TLS_VALIDATION_MODE === 'permissive',
            
            // Security features
            enableNetworkTracing: process.env.ENABLE_NETWORK_TRACE === 'true',
            screenshotOnFailure: process.env.SCREENSHOT_ON_FAILURE !== 'false',
            
            // Resource limits
            maxMemoryMB: parseInt(process.env.MAX_BROWSER_MEMORY) || 512,
            maxDiskMB: parseInt(process.env.MAX_BROWSER_DISK) || 100,
            
            // Results directories
            resultsDir: process.env.TEST_RESULTS_DIR || './test-results',
            screenshotsDir: process.env.TEST_SCREENSHOTS_DIR || './test-screenshots'
        };
    }

    /**
     * Create secure browser instance with hardened configuration
     * @param {string} browserType - Browser type (chromium, firefox, webkit)
     * @param {Object} options - Additional browser options
     * @returns {Promise<Object>} Browser instance with security metadata
     */
    async createSecureBrowser(browserType = 'chromium', options = {}) {
        const browsers = { chromium, firefox, webkit };
        const browserEngine = browsers[browserType];
        
        if (!browserEngine) {
            throw new Error(`Unsupported browser type: ${browserType}`);
        }

        // Build secure launch options
        const launchOptions = this.buildSecureLaunchOptions(browserType, options);
        
        // Launch browser with security configuration
        const browser = await browserEngine.launch(launchOptions);
        const browserId = this.generateBrowserId();
        
        // Store browser reference
        this.activeBrowsers.set(browserId, {
            browser,
            browserType,
            created: new Date().toISOString(),
            options: launchOptions
        });

        // Log browser creation
        await this.credentialManager.auditLogger('BROWSER_CREATED', {
            browserId,
            browserType,
            headless: launchOptions.headless,
            securityFeatures: this.getSecurityFeaturesSummary(launchOptions)
        });

        return {
            browser,
            browserId,
            createSecureContext: (contextOptions = {}) => 
                this.createSecureContext(browserId, contextOptions)
        };
    }

    /**
     * Build secure browser launch options
     * @param {string} browserType - Browser type
     * @param {Object} userOptions - User-provided options
     * @returns {Object} Secure launch options
     */
    buildSecureLaunchOptions(browserType, userOptions) {
        const baseOptions = {
            headless: this.securityConfig.headless,
            slowMo: this.securityConfig.slowMo,
            timeout: this.securityConfig.timeout
        };

        // Browser-specific security hardening
        if (browserType === 'chromium') {
            baseOptions.args = this.buildSecureChromiumArgs();
        } else if (browserType === 'firefox') {
            baseOptions.firefoxUserPrefs = this.buildSecureFirefoxPrefs();
        }

        // SSL/TLS configuration
        baseOptions.ignoreHTTPSErrors = this.securityConfig.ignoreCertificateErrors;

        // Merge with user options (security options take precedence)
        const mergedOptions = { ...userOptions, ...baseOptions };
        
        // Validate security-critical options
        this.validateSecurityOptions(mergedOptions);
        
        return mergedOptions;
    }

    /**
     * Build secure Chromium arguments
     * @returns {Array} Secure Chrome arguments
     */
    buildSecureChromiumArgs() {
        const secureArgs = [
            // Security hardening
            '--disable-web-security=false',  // Enable web security
            '--disable-features=TranslateUI',
            '--disable-ipc-flooding-protection=false',
            '--disable-renderer-backgrounding',
            '--disable-backgrounding-occluded-windows',
            '--disable-background-timer-throttling',
            '--disable-component-extensions-with-background-pages',
            
            // Memory and resource limits
            '--max-old-space-size=512',
            '--memory-pressure-off',
            
            // Network security
            '--no-proxy-server',
            '--disable-sync',
            '--disable-translate',
            
            // Content security
            '--disable-plugins',
            '--disable-flash-3d',
            '--disable-flash-stage3d'
        ];

        // Add sandbox control based on environment
        if (process.env.CONTAINER_MODE === 'true') {
            // In containers, we need to disable sandbox due to user namespace issues
            secureArgs.push('--no-sandbox', '--disable-setuid-sandbox');
            console.warn('⚠️  Running in container mode with reduced sandbox security');
        } else {
            // In normal environments, keep sandbox enabled
            console.log('✅ Running with full sandbox security');
        }

        return secureArgs;
    }

    /**
     * Build secure Firefox preferences
     * @returns {Object} Secure Firefox preferences
     */
    buildSecureFirefoxPrefs() {
        return {
            // Security preferences
            'security.tls.insecure_fallback_hosts': '',
            'security.mixed_content.block_active_content': true,
            'security.mixed_content.block_display_content': true,
            
            // Privacy preferences
            'privacy.trackingprotection.enabled': true,
            'privacy.donottrackheader.enabled': true,
            
            // Network preferences
            'network.http.sendOriginHeader': 1,
            'network.cookie.cookieBehavior': 1
        };
    }

    /**
     * Validate security-critical browser options
     * @param {Object} options - Browser options to validate
     */
    validateSecurityOptions(options) {
        // Check for dangerous options
        const dangerousOptions = [
            'devtools', // Don't allow devtools in automated testing
            'userDataDir' // Prevent data persistence
        ];

        for (const dangerous of dangerousOptions) {
            if (options[dangerous]) {
                throw new Error(`Security violation: ${dangerous} option not allowed`);
            }
        }

        // Validate arguments for security
        if (options.args) {
            const dangerousArgs = [
                '--disable-web-security',
                '--allow-running-insecure-content',
                '--disable-security-warnings'
            ];

            for (const arg of options.args) {
                if (dangerousArgs.some(dangerous => arg.includes(dangerous))) {
                    throw new Error(`Security violation: dangerous argument not allowed: ${arg}`);
                }
            }
        }
    }

    /**
     * Create secure browser context with authentication and security controls
     * @param {string} browserId - Browser ID
     * @param {Object} contextOptions - Context options
     * @returns {Promise<Object>} Secure context with authentication helpers
     */
    async createSecureContext(browserId, contextOptions = {}) {
        const browserInfo = this.activeBrowsers.get(browserId);
        if (!browserInfo) {
            throw new Error('Browser not found');
        }

        // Build secure context options
        const secureContextOptions = this.buildSecureContextOptions(contextOptions);
        
        // Create context
        const context = await browserInfo.browser.newContext(secureContextOptions);
        const contextId = this.generateContextId();

        // Store context reference
        this.activeContexts.set(contextId, {
            context,
            browserId,
            created: new Date().toISOString(),
            options: secureContextOptions
        });

        // Set up security monitoring
        await this.setupSecurityMonitoring(context, contextId);

        // Create authentication helpers
        const authHelpers = this.createAuthenticationHelpers(context, contextId);

        await this.credentialManager.auditLogger('BROWSER_CONTEXT_CREATED', {
            contextId,
            browserId,
            securityFeatures: this.getContextSecurityFeatures(secureContextOptions)
        });

        return {
            context,
            contextId,
            ...authHelpers,
            createSecurePage: () => this.createSecurePage(contextId)
        };
    }

    /**
     * Build secure context options
     * @param {Object} userOptions - User context options
     * @returns {Object} Secure context options
     */
    buildSecureContextOptions(userOptions) {
        const baseOptions = {
            viewport: { width: 1280, height: 720 },
            userAgent: 'HVAC-Testing-Framework/1.0 (Security-Hardened)',
            ignoreHTTPSErrors: this.securityConfig.ignoreCertificateErrors,
            
            // Permissions and security
            permissions: [], // No permissions by default
            geolocation: undefined, // No geolocation
            locale: 'en-US',
            
            // Recording options (secure)
            recordVideo: undefined, // No video recording for security
            recordHar: this.securityConfig.enableNetworkTracing ? {
                mode: 'minimal',
                content: 'omit' // Don't record response bodies
            } : undefined
        };

        // Add base URL from secure configuration
        baseOptions.baseURL = this.credentialManager.getBaseUrl();

        return { ...baseOptions, ...userOptions };
    }

    /**
     * Set up security monitoring for browser context
     * @param {Object} context - Browser context
     * @param {string} contextId - Context ID
     */
    async setupSecurityMonitoring(context, contextId) {
        // Monitor network requests for security
        context.on('request', async (request) => {
            const url = request.url();
            
            // Block dangerous requests
            if (this.isBlockedRequest(url)) {
                await request.abort('blockedbyclient');
                await this.credentialManager.auditLogger('REQUEST_BLOCKED', {
                    contextId,
                    url,
                    reason: 'security_policy'
                });
                return;
            }

            // Log sensitive requests
            if (this.isSensitiveRequest(url)) {
                await this.credentialManager.auditLogger('SENSITIVE_REQUEST', {
                    contextId,
                    url: this.sanitizeUrlForLogging(url),
                    method: request.method()
                });
            }
        });

        // Monitor responses for errors
        context.on('response', async (response) => {
            if (response.status() >= 400) {
                await this.credentialManager.auditLogger('HTTP_ERROR', {
                    contextId,
                    url: this.sanitizeUrlForLogging(response.url()),
                    status: response.status()
                });
            }
        });

        // Monitor console messages for security issues
        context.on('console', async (message) => {
            const text = message.text();
            if (this.isSecurityRelevantConsoleMessage(text)) {
                await this.credentialManager.auditLogger('SECURITY_CONSOLE_MESSAGE', {
                    contextId,
                    type: message.type(),
                    message: this.sanitizeConsoleMessage(text)
                });
            }
        });
    }

    /**
     * Create authentication helpers for secure login
     * @param {Object} context - Browser context
     * @param {string} contextId - Context ID
     * @returns {Object} Authentication helper methods
     */
    createAuthenticationHelpers(context, contextId) {
        return {
            /**
             * Authenticate as a specific user role
             * @param {string} role - User role
             * @returns {Promise<Object>} Authentication result
             */
            authenticateAs: async (role) => {
                const session = this.credentialManager.createSecureSession(role);
                const credentials = this.credentialManager.getSessionCredentials(session.sessionId);
                
                const page = await context.newPage();
                
                try {
                    // Navigate to login page
                    const loginUrl = `${this.credentialManager.getBaseUrl()}/training-login/`;
                    await page.goto(loginUrl, { waitUntil: 'networkidle' });

                    // Perform secure login
                    await this.performSecureLogin(page, credentials, contextId);

                    // Verify authentication
                    await this.verifyAuthentication(page, credentials.role, contextId);

                    await this.credentialManager.auditLogger('AUTHENTICATION_SUCCESS', {
                        contextId,
                        role: credentials.role,
                        sessionId: session.sessionId
                    });

                    return {
                        success: true,
                        role: credentials.role,
                        sessionId: session.sessionId,
                        page
                    };
                } catch (error) {
                    await page.close();
                    this.credentialManager.destroySession(session.sessionId);
                    
                    await this.credentialManager.auditLogger('AUTHENTICATION_FAILED', {
                        contextId,
                        role,
                        error: error.message
                    });
                    
                    throw error;
                }
            },

            /**
             * Logout and clean up session
             * @param {string} sessionId - Session ID to destroy
             * @returns {Promise<void>}
             */
            logout: async (sessionId) => {
                if (sessionId) {
                    this.credentialManager.destroySession(sessionId);
                    await this.credentialManager.auditLogger('LOGOUT_COMPLETED', {
                        contextId,
                        sessionId
                    });
                }
            }
        };
    }

    /**
     * Perform secure login with credential validation
     * @param {Object} page - Playwright page
     * @param {Object} credentials - User credentials
     * @param {string} contextId - Context ID
     */
    async performSecureLogin(page, credentials, contextId) {
        // Look for login form elements
        const usernameSelectors = [
            'input[name="log"]',
            'input[name="username"]', 
            '#user_login',
            '#username'
        ];
        
        const passwordSelectors = [
            'input[name="pwd"]',
            'input[name="password"]',
            '#user_pass',
            '#password'
        ];

        // Find and fill username
        let usernameField = null;
        for (const selector of usernameSelectors) {
            try {
                usernameField = page.locator(selector);
                if (await usernameField.count() > 0) {
                    await usernameField.fill(credentials.username);
                    break;
                }
            } catch (e) {
                continue;
            }
        }

        if (!usernameField || await usernameField.count() === 0) {
            throw new Error('Username field not found');
        }

        // Find and fill password
        let passwordField = null;
        for (const selector of passwordSelectors) {
            try {
                passwordField = page.locator(selector);
                if (await passwordField.count() > 0) {
                    await passwordField.fill(credentials.password);
                    break;
                }
            } catch (e) {
                continue;
            }
        }

        if (!passwordField || await passwordField.count() === 0) {
            throw new Error('Password field not found');
        }

        // Submit login form
        const submitSelectors = [
            'button[type="submit"]',
            'input[type="submit"]',
            '#wp-submit',
            '.wp-submit'
        ];

        let submitted = false;
        for (const selector of submitSelectors) {
            try {
                const submitButton = page.locator(selector);
                if (await submitButton.count() > 0) {
                    await submitButton.click();
                    submitted = true;
                    break;
                }
            } catch (e) {
                continue;
            }
        }

        if (!submitted) {
            throw new Error('Submit button not found');
        }

        // Wait for navigation
        await page.waitForLoadState('networkidle', { timeout: 15000 });
    }

    /**
     * Verify successful authentication
     * @param {Object} page - Playwright page
     * @param {string} expectedRole - Expected user role
     * @param {string} contextId - Context ID
     */
    async verifyAuthentication(page, expectedRole, contextId) {
        // Check for authentication success indicators
        const currentUrl = page.url();
        
        // Should not be on login page after successful authentication
        if (currentUrl.includes('/training-login/') || currentUrl.includes('/wp-login.php')) {
            throw new Error('Authentication failed - still on login page');
        }

        // Role-specific URL verification
        const roleUrlPatterns = {
            'hvac_master_trainer': /\/master-trainer\//,
            'hvac_trainer': /\/trainer\//,
            'administrator': /\/wp-admin\//
        };

        if (roleUrlPatterns[expectedRole] && !roleUrlPatterns[expectedRole].test(currentUrl)) {
            console.warn(`Authentication successful but unexpected URL pattern for role ${expectedRole}: ${currentUrl}`);
        }

        // Additional verification by checking page content
        const bodyText = await page.textContent('body');
        
        // Should not contain login-related error messages
        const errorIndicators = [
            'invalid username',
            'invalid password', 
            'login failed',
            'authentication error'
        ];

        for (const indicator of errorIndicators) {
            if (bodyText.toLowerCase().includes(indicator)) {
                throw new Error(`Authentication failed: ${indicator} detected`);
            }
        }
    }

    /**
     * Create secure page with monitoring and security controls
     * @param {string} contextId - Context ID
     * @returns {Promise<Object>} Secure page with helpers
     */
    async createSecurePage(contextId) {
        const contextInfo = this.activeContexts.get(contextId);
        if (!contextInfo) {
            throw new Error('Context not found');
        }

        const page = await contextInfo.context.newPage();
        
        // Set security headers
        await page.setExtraHTTPHeaders({
            'X-Security-Test': 'HVAC-Framework',
            'Cache-Control': 'no-cache, no-store'
        });

        return {
            page,
            secureGoto: (url, options = {}) => this.securePageGoto(page, url, options, contextId),
            secureScreenshot: (options = {}) => this.secureScreenshot(page, options, contextId)
        };
    }

    /**
     * Secure page navigation with URL validation
     * @param {Object} page - Playwright page
     * @param {string} url - URL to navigate to
     * @param {Object} options - Navigation options
     * @param {string} contextId - Context ID
     */
    async securePageGoto(page, url, options, contextId) {
        // Validate URL
        if (!this.isAllowedUrl(url)) {
            throw new Error(`URL not allowed: ${url}`);
        }

        // Navigate with security monitoring
        const response = await page.goto(url, {
            waitUntil: 'networkidle',
            timeout: this.securityConfig.timeout,
            ...options
        });

        // Log navigation
        await this.credentialManager.auditLogger('PAGE_NAVIGATION', {
            contextId,
            url: this.sanitizeUrlForLogging(url),
            status: response ? response.status() : 'unknown'
        });

        return response;
    }

    /**
     * Take secure screenshot with metadata
     * @param {Object} page - Playwright page
     * @param {Object} options - Screenshot options
     * @param {string} contextId - Context ID
     */
    async secureScreenshot(page, options, contextId) {
        const filename = options.path || 
            path.join(this.securityConfig.screenshotsDir, `screenshot-${contextId}-${Date.now()}.png`);
        
        // Ensure screenshots directory exists
        await fs.mkdir(path.dirname(filename), { recursive: true });

        const screenshot = await page.screenshot({
            fullPage: true,
            ...options,
            path: filename
        });

        await this.credentialManager.auditLogger('SCREENSHOT_TAKEN', {
            contextId,
            filename,
            size: screenshot.length
        });

        return screenshot;
    }

    /**
     * Utility methods for security validation
     */

    generateBrowserId() {
        return `browser-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    }

    generateContextId() {
        return `context-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
    }

    isBlockedRequest(url) {
        const blockedPatterns = [
            /facebook\.com/,
            /google-analytics\.com/,
            /googletagmanager\.com/,
            /doubleclick\.net/,
            /\.ads\./
        ];
        
        return blockedPatterns.some(pattern => pattern.test(url));
    }

    isSensitiveRequest(url) {
        return url.includes('login') || url.includes('auth') || url.includes('password');
    }

    isSecurityRelevantConsoleMessage(message) {
        const securityKeywords = [
            'security', 'error', 'warning', 'blocked', 'cors', 'csp',
            'mixed content', 'certificate', 'ssl', 'tls'
        ];
        
        const lowerMessage = message.toLowerCase();
        return securityKeywords.some(keyword => lowerMessage.includes(keyword));
    }

    isAllowedUrl(url) {
        const baseUrl = this.credentialManager.getBaseUrl();
        return url.startsWith(baseUrl) || url.startsWith('data:') || url.startsWith('about:');
    }

    sanitizeUrlForLogging(url) {
        return url.replace(/[?&](password|pwd|token|key)=[^&]+/gi, '$1=***');
    }

    sanitizeConsoleMessage(message) {
        return message.replace(/password[=:]\s*[^\s]+/gi, 'password=***')
                      .replace(/token[=:]\s*[^\s]+/gi, 'token=***');
    }

    getSecurityFeaturesSummary(options) {
        return {
            headless: options.headless,
            sandboxEnabled: !options.args?.includes('--no-sandbox'),
            tlsValidation: !options.ignoreHTTPSErrors
        };
    }

    getContextSecurityFeatures(options) {
        return {
            httpsOnly: !options.ignoreHTTPSErrors,
            permissionsLimited: options.permissions?.length === 0,
            networkMonitoring: !!options.recordHar
        };
    }

    /**
     * Clean up all browsers and contexts
     */
    async cleanup() {
        for (const [contextId, contextInfo] of this.activeContexts) {
            try {
                await contextInfo.context.close();
            } catch (error) {
                console.warn(`Failed to close context ${contextId}:`, error.message);
            }
        }
        this.activeContexts.clear();

        for (const [browserId, browserInfo] of this.activeBrowsers) {
            try {
                await browserInfo.browser.close();
            } catch (error) {
                console.warn(`Failed to close browser ${browserId}:`, error.message);
            }
        }
        this.activeBrowsers.clear();

        await this.credentialManager.auditLogger('BROWSER_CLEANUP_COMPLETED');
    }
}

// Singleton instance
let browserManagerInstance = null;

/**
 * Get singleton instance of SecureBrowserManager
 * @returns {SecureBrowserManager}
 */
function getBrowserManager() {
    if (!browserManagerInstance) {
        browserManagerInstance = new SecureBrowserManager();
    }
    return browserManagerInstance;
}

module.exports = {
    SecureBrowserManager,
    getBrowserManager
};