/**
 * Base Page Object Model for HVAC Testing Framework
 * 
 * Provides common functionality for all page objects:
 * - WordPress-specific element interactions
 * - Consistent selector patterns with data-testid support
 * - Error handling and retry mechanisms
 * - Screenshot management
 * - WordPress AJAX and loading state handling
 * 
 * @package HVAC_Community_Events
 * @version 2.0.0
 * @created 2025-08-27
 */

const { expect } = require('@playwright/test');
const ConfigManager = require('../core/ConfigManager');

class BasePage {
    constructor(page) {
        this.page = page;
        this.config = ConfigManager;
        this.baseUrl = this.config.get('app.baseUrl');
        this.timeout = this.config.get('framework.timeout');
    }
    
    /**
     * Navigate to page with WordPress-aware waiting
     */
    async goto(url, options = {}) {
        const fullUrl = url.startsWith('http') ? url : `${this.baseUrl}${url}`;
        
        console.log(`🔗 Navigating to: ${fullUrl}`);
        
        await this.page.goto(fullUrl, {
            waitUntil: 'networkidle',
            timeout: this.timeout,
            ...options
        });
        
        // Wait for WordPress to be ready
        await this.waitForWordPressReady();
    }
    
    /**
     * Wait for WordPress to be fully loaded
     */
    async waitForWordPressReady() {
        // Wait for DOM to be ready
        await this.page.waitForFunction('document.readyState === "complete"');
        
        // Wait for jQuery if present
        await this.page.waitForFunction(`
            !window.jQuery || jQuery.active === 0
        `, { timeout: 5000 }).catch(() => {
            // jQuery not present or still active, that's fine
        });
        
        // Wait for WordPress admin bar if present
        await this.page.waitForFunction(`
            !document.querySelector('#wpadminbar') || 
            document.querySelector('#wpadminbar').style.display !== 'none'
        `, { timeout: 2000 }).catch(() => {
            // Admin bar not present, that's fine
        });
    }
    
    /**
     * Find element using multiple selector strategies
     * Prioritizes data-testid, then data-role, then CSS selectors
     */
    locator(selectors, options = {}) {
        if (typeof selectors === 'string') {
            selectors = [selectors];
        }
        
        // Build selector list with priority
        const selectorList = [];
        
        for (const selector of selectors) {
            // Check if it's a test ID
            if (!selector.includes('[') && !selector.includes('.') && !selector.includes('#')) {
                selectorList.push(`[data-testid="${selector}"]`);
            }
            
            // Add the original selector
            selectorList.push(selector);
        }
        
        // Try selectors in order
        for (const selector of selectorList) {
            const locator = this.page.locator(selector);
            if (options.first) {
                return locator.first();
            }
            return locator;
        }
        
        // Fallback to first selector
        return this.page.locator(selectors[0]);
    }
    
    /**
     * Click element with WordPress-aware waiting
     */
    async click(selectors, options = {}) {
        const element = this.locator(selectors, options);
        
        // Wait for element to be visible and enabled
        await element.waitFor({ state: 'visible', timeout: options.timeout || this.timeout });
        await element.waitFor({ state: 'attached' });
        
        // Scroll into view if needed
        await element.scrollIntoViewIfNeeded();
        
        // Click with optional navigation waiting
        if (options.waitForNavigation) {
            await Promise.all([
                this.page.waitForLoadState('networkidle'),
                element.click()
            ]);
        } else {
            await element.click();
        }
        
        // Wait for AJAX if WordPress
        if (!options.skipAjaxWait) {
            await this.waitForAjax();
        }
        
        return element;
    }
    
    /**
     * Fill form field with validation
     */
    async fill(selectors, value, options = {}) {
        const element = this.locator(selectors, options);
        
        await element.waitFor({ state: 'visible', timeout: options.timeout || this.timeout });
        
        // Clear field first if not disabled
        if (options.clear !== false) {
            await element.clear();
        }
        
        // Fill value
        await element.fill(value);
        
        // Validate the value was set correctly
        if (options.validate !== false) {
            const actualValue = await element.inputValue();
            if (actualValue !== value) {
                throw new Error(`Expected field value "${value}", but got "${actualValue}"`);
            }
        }
        
        return element;
    }
    
    /**
     * Wait for element to be visible
     */
    async waitForVisible(selectors, options = {}) {
        const element = this.locator(selectors, options);
        await element.waitFor({ 
            state: 'visible', 
            timeout: options.timeout || this.timeout 
        });
        return element;
    }
    
    /**
     * Wait for element to be hidden
     */
    async waitForHidden(selectors, options = {}) {
        const element = this.locator(selectors, options);
        await element.waitFor({ 
            state: 'hidden', 
            timeout: options.timeout || this.timeout 
        });
        return element;
    }
    
    /**
     * Wait for WordPress AJAX requests to complete
     */
    async waitForAjax(timeout = 5000) {
        try {
            await this.page.waitForFunction(`
                !window.jQuery || jQuery.active === 0
            `, { timeout });
        } catch (error) {
            // AJAX wait timed out, which is acceptable
            console.warn('AJAX wait timed out, continuing...');
        }
    }
    
    /**
     * Check if element exists and is visible
     */
    async isVisible(selectors, options = {}) {
        try {
            const element = this.locator(selectors, options);
            return await element.isVisible();
        } catch (error) {
            return false;
        }
    }
    
    /**
     * Get text content from element
     */
    async getText(selectors, options = {}) {
        const element = this.locator(selectors, options);
        await element.waitFor({ state: 'visible', timeout: options.timeout || 5000 });
        return await element.textContent();
    }
    
    /**
     * Get attribute value from element
     */
    async getAttribute(selectors, attributeName, options = {}) {
        const element = this.locator(selectors, options);
        await element.waitFor({ state: 'attached', timeout: options.timeout || 5000 });
        return await element.getAttribute(attributeName);
    }
    
    /**
     * Check WordPress nonce exists on page
     */
    async verifyNonce(nonceName = '_wpnonce') {
        const nonceExists = await this.page.locator(`input[name="${nonceName}"]`).count() > 0;
        if (!nonceExists) {
            throw new Error(`WordPress nonce '${nonceName}' not found on page`);
        }
        return true;
    }
    
    /**
     * Wait for WordPress admin notice
     */
    async waitForNotice(type = 'success', timeout = 5000) {
        const noticeSelector = `.notice-${type}, .updated, .notice.notice-${type}`;
        await this.page.waitForSelector(noticeSelector, { timeout });
        return await this.page.locator(noticeSelector).textContent();
    }
    
    /**
     * Dismiss WordPress admin notices
     */
    async dismissNotices() {
        const dismissButtons = this.page.locator('.notice-dismiss, .dismiss');
        const count = await dismissButtons.count();
        
        for (let i = 0; i < count; i++) {
            try {
                await dismissButtons.nth(i).click();
                await this.page.waitForTimeout(200); // Small delay between dismissals
            } catch (error) {
                // Notice already dismissed or not interactive
            }
        }
        
        console.log(`📄 Dismissed ${count} admin notices`);
    }
    
    /**
     * Handle WordPress modal dialogs
     */
    async handleModal(action = 'accept', options = {}) {
        this.page.on('dialog', async dialog => {
            console.log(`🗨️ Dialog: ${dialog.message()}`);
            
            if (action === 'accept') {
                await dialog.accept(options.promptText);
            } else {
                await dialog.dismiss();
            }
        });
    }
    
    /**
     * Take screenshot with context
     */
    async takeScreenshot(name, options = {}) {
        const screenshotPath = `${this.config.get('media.screenshotDir')}/${name}-${Date.now()}.png`;
        
        await this.page.screenshot({
            path: screenshotPath,
            fullPage: options.fullPage || false,
            quality: options.quality || this.config.get('media.quality'),
            ...options
        });
        
        console.log(`📸 Screenshot saved: ${screenshotPath}`);
        return screenshotPath;
    }
    
    /**
     * Scroll to element
     */
    async scrollTo(selectors, options = {}) {
        const element = this.locator(selectors, options);
        await element.scrollIntoViewIfNeeded();
        
        // Additional scroll offset if needed
        if (options.offset) {
            await this.page.evaluate((offset) => {
                window.scrollBy(0, offset);
            }, options.offset);
        }
    }
    
    /**
     * Wait for page URL to match pattern
     */
    async waitForUrl(pattern, options = {}) {
        await this.page.waitForURL(pattern, {
            timeout: options.timeout || this.timeout,
            ...options
        });
    }
    
    /**
     * Verify page title
     */
    async verifyTitle(expectedTitle) {
        const actualTitle = await this.page.title();
        expect(actualTitle).toContain(expectedTitle);
    }
    
    /**
     * Verify breadcrumb navigation
     */
    async verifyBreadcrumbs(expectedBreadcrumbs) {
        const breadcrumbs = await this.page.locator('.hvac-breadcrumb a, .breadcrumb a').allTextContents();
        
        for (const expectedCrumb of expectedBreadcrumbs) {
            expect(breadcrumbs).toContain(expectedCrumb);
        }
    }
    
    /**
     * Check if user is authenticated (WordPress-specific)
     */
    async isAuthenticated() {
        const indicators = [
            '#wpadminbar',           // WordPress admin bar
            '.logged-in',           // Body class for logged-in users
            '.hvac-trainer-nav',    // HVAC trainer navigation
            '.hvac-master-nav'      // HVAC master trainer navigation
        ];
        
        for (const indicator of indicators) {
            if (await this.isVisible(indicator)) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Get current user role from page context
     */
    async getCurrentUserRole() {
        return await this.page.evaluate(() => {
            // Check body classes
            const bodyClasses = document.body.className;
            
            if (bodyClasses.includes('role-hvac_master_trainer')) {
                return 'masterTrainer';
            } else if (bodyClasses.includes('role-hvac_trainer')) {
                return 'trainer';
            } else if (bodyClasses.includes('role-administrator')) {
                return 'admin';
            }
            
            // Check navigation elements
            if (document.querySelector('.hvac-master-nav')) {
                return 'masterTrainer';
            } else if (document.querySelector('.hvac-trainer-nav')) {
                return 'trainer';
            }
            
            // Check URL patterns
            const path = window.location.pathname;
            if (path.includes('/master-trainer/')) {
                return 'masterTrainer';
            } else if (path.includes('/trainer/')) {
                return 'trainer';
            } else if (path.includes('/wp-admin/')) {
                return 'admin';
            }
            
            return 'unknown';
        });
    }
    
    /**
     * Verify user has expected role
     */
    async verifyUserRole(expectedRole) {
        const currentRole = await this.getCurrentUserRole();
        expect(currentRole).toBe(expectedRole);
    }
    
    /**
     * Generic form submission with WordPress nonce handling
     */
    async submitForm(formSelector, options = {}) {
        const form = this.locator(formSelector);
        await form.waitFor({ state: 'visible' });
        
        // Verify nonce if required
        if (options.verifyNonce !== false) {
            try {
                await this.verifyNonce(options.nonceName);
            } catch (error) {
                console.warn('Nonce verification failed:', error.message);
            }
        }
        
        // Submit form
        if (options.submitButton) {
            await this.click(options.submitButton, { waitForNavigation: true });
        } else {
            await form.press('Enter');
        }
        
        // Wait for response
        await this.waitForAjax();
        
        if (options.waitForNotice) {
            try {
                const noticeText = await this.waitForNotice(options.noticeType || 'success');
                console.log(`✅ Form submitted successfully: ${noticeText}`);
            } catch (error) {
                console.warn('No success notice found after form submission');
            }
        }
    }
}

module.exports = BasePage;