/**
 * Browser Manager - Centralized browser lifecycle management
 * Provides singleton browser instances with proper cleanup and configuration
 */

const { chromium, firefox, webkit } = require('playwright');
const path = require('path');

class BrowserManager {
    constructor() {
        this.browser = null;
        this.context = null;
        this.page = null;
        this.config = null;
    }

    /**
     * Initialize browser with configuration
     * @param {Object} config - Browser configuration
     * @returns {Promise<void>}
     */
    async initialize(config) {
        this.config = {
            browserType: 'chromium',
            headless: true,
            slowMo: 0,
            timeout: 30000,
            viewport: { width: 1280, height: 720 },
            video: false,
            screenshot: 'only-on-failure',
            ...config
        };

        // Launch browser based on type
        const browserType = this._getBrowserType(this.config.browserType);
        
        this.browser = await browserType.launch({
            headless: this.config.headless,
            slowMo: this.config.slowMo,
            args: this._getBrowserArgs()
        });

        // Create context with configuration
        this.context = await this.browser.newContext({
            viewport: this.config.viewport,
            video: this.config.video ? { 
                dir: path.join(process.cwd(), 'tests/evidence/videos') 
            } : undefined,
            recordVideo: this.config.video ? {
                dir: path.join(process.cwd(), 'tests/evidence/videos'),
                size: this.config.viewport
            } : undefined
        });

        // Set default timeout
        this.context.setDefaultTimeout(this.config.timeout);

        // Create initial page
        this.page = await this.context.newPage();
        
        // Set up page defaults
        await this._setupPageDefaults();

        return { browser: this.browser, context: this.context, page: this.page };
    }

    /**
     * Get new page instance
     * @returns {Promise<Page>}
     */
    async getNewPage() {
        if (!this.context) {
            throw new Error('Browser not initialized. Call initialize() first.');
        }
        return await this.context.newPage();
    }

    /**
     * Get current page
     * @returns {Page}
     */
    getCurrentPage() {
        if (!this.page) {
            throw new Error('No active page. Browser may not be initialized.');
        }
        return this.page;
    }

    /**
     * Close current page
     * @returns {Promise<void>}
     */
    async closePage() {
        if (this.page) {
            await this.page.close();
            this.page = null;
        }
    }

    /**
     * Clean shutdown of browser
     * @returns {Promise<void>}
     */
    async cleanup() {
        try {
            if (this.page) {
                await this.page.close();
                this.page = null;
            }
            if (this.context) {
                await this.context.close();
                this.context = null;
            }
            if (this.browser) {
                await this.browser.close();
                this.browser = null;
            }
        } catch (error) {
            console.warn('Error during browser cleanup:', error.message);
        }
    }

    /**
     * Take screenshot of current page
     * @param {string} filename - Screenshot filename
     * @param {Object} options - Screenshot options
     * @returns {Promise<string>} Path to screenshot
     */
    async takeScreenshot(filename, options = {}) {
        if (!this.page) {
            throw new Error('No active page for screenshot');
        }

        const screenshotPath = path.join(
            process.cwd(), 
            'tests/evidence/screenshots', 
            filename
        );

        await this.page.screenshot({
            path: screenshotPath,
            fullPage: true,
            ...options
        });

        return screenshotPath;
    }

    /**
     * Wait for page load with network idle
     * @param {number} timeout - Wait timeout
     * @returns {Promise<void>}
     */
    async waitForPageLoad(timeout = 30000) {
        if (!this.page) return;
        
        try {
            await this.page.waitForLoadState('networkidle', { timeout });
        } catch (error) {
            console.warn('Page load wait timeout:', error.message);
        }
    }

    /**
     * Get browser type instance
     * @param {string} browserType - Browser type name
     * @returns {BrowserType}
     * @private
     */
    _getBrowserType(browserType) {
        switch (browserType.toLowerCase()) {
            case 'firefox':
                return firefox;
            case 'webkit':
            case 'safari':
                return webkit;
            case 'chromium':
            case 'chrome':
            default:
                return chromium;
        }
    }

    /**
     * Get browser launch arguments
     * @returns {string[]}
     * @private
     */
    _getBrowserArgs() {
        return [
            '--no-sandbox',
            '--disable-dev-shm-usage',
            '--disable-extensions',
            '--disable-background-timer-throttling',
            '--disable-backgrounding-occluded-windows',
            '--disable-renderer-backgrounding',
            '--disable-features=TranslateUI',
            '--no-default-browser-check',
            '--no-first-run'
        ];
    }

    /**
     * Set up default page configuration
     * @returns {Promise<void>}
     * @private
     */
    async _setupPageDefaults() {
        if (!this.page) return;

        // Set user agent
        await this.page.setExtraHTTPHeaders({
            'User-Agent': 'HVAC-Testing-Framework/2.0'
        });

        // Set up console logging
        this.page.on('console', (msg) => {
            if (msg.type() === 'error') {
                console.error('Browser console error:', msg.text());
            }
        });

        // Set up page error handling
        this.page.on('pageerror', (error) => {
            console.error('Page error:', error.message);
        });

        // Set up network error handling
        this.page.on('requestfailed', (request) => {
            console.warn('Request failed:', request.url(), request.failure()?.errorText);
        });
    }
}

// Singleton instance
let browserManager = null;

/**
 * Get singleton BrowserManager instance
 * @returns {BrowserManager}
 */
function getBrowserManager() {
    if (!browserManager) {
        browserManager = new BrowserManager();
    }
    return browserManager;
}

module.exports = { BrowserManager, getBrowserManager };