/**
 * Login Page Object Model
 * 
 * Provides a clean interface for login functionality across all test suites:
 * - Role-based authentication
 * - Multiple login form handling
 * - Authentication state management
 * - Error handling and validation
 * - Session persistence
 * 
 * @package HVAC_Community_Events
 * @version 3.0.0
 * @created 2025-08-20
 */

const { expect } = require('@playwright/test');
const { 
    AUTH_CONFIG, 
    performLogin, 
    performLogout, 
    verifyAuthentication,
    saveAuthState,
    getAuthStatePath,
    getUserConfig
} = require('./auth.setup');

class LoginPage {
    constructor(page) {
        this.page = page;
        
        // Selectors for different login forms
        this.selectors = {
            // Standard WordPress login
            wpLogin: {
                form: '#loginform',
                email: '#user_login',
                password: '#user_pass',
                submit: '#wp-submit',
                error: '#login_error',
                rememberMe: '#rememberme'
            },
            
            // Custom HVAC training login
            hvacLogin: {
                form: '.login-form, .hvac-login-form',
                email: 'input[type="email"], input[name="log"]',
                password: 'input[type="password"], input[name="pwd"]',
                submit: 'button[type="submit"], input[type="submit"]',
                error: '.login-error, .error-message',
                rememberMe: 'input[name="rememberme"]'
            },
            
            // Generic selectors as fallback
            generic: {
                email: 'input[type="email"], #user_login, input[name="log"]',
                password: 'input[type="password"], #user_pass, input[name="pwd"]',
                submit: 'button[type="submit"], input[type="submit"], #wp-submit'
            }
        };
        
        // Navigation selectors for verification
        this.navigation = {
            trainerDashboard: 'text=Dashboard, text=Trainer Dashboard, h1:has-text("Dashboard")',
            masterDashboard: 'text=Master Dashboard, text=Master Trainer Dashboard',
            adminDashboard: '#wpadminbar, .wp-admin, #wpbody',
            logoutLink: 'a[href*="logout"], text=Logout, text=Log Out'
        };
    }
    
    /**
     * Navigate to appropriate login page based on user type
     * @param {string} userType - User type (trainer, master_trainer, admin)
     * @param {Object} options - Navigation options
     */
    async navigateToLogin(userType = 'trainer', options = {}) {
        const user = getUserConfig(userType);
        const useWpLogin = options.useWpLogin || userType === 'admin';
        const loginPath = useWpLogin ? AUTH_CONFIG.wpLoginUrl : AUTH_CONFIG.loginUrl;
        const loginUrl = `${AUTH_CONFIG.baseUrl}${loginPath}`;
        
        console.log(`🔗 Navigating to login page: ${loginUrl}`);
        
        await this.page.goto(loginUrl, {
            waitUntil: 'networkidle',
            timeout: AUTH_CONFIG.timeout
        });
        
        // Wait for login form to be ready
        await this.waitForLoginForm();
    }
    
    /**
     * Wait for login form to be present and ready
     */
    async waitForLoginForm() {
        // Try to detect which type of login form is present
        try {
            await this.page.waitForSelector(this.selectors.generic.email, { timeout: 10000 });
            await this.page.waitForSelector(this.selectors.generic.password, { timeout: 5000 });
            await this.page.waitForSelector(this.selectors.generic.submit, { timeout: 5000 });
        } catch (error) {
            throw new Error('Login form not found or not ready');
        }
    }
    
    /**
     * Perform login with specified user credentials
     * @param {string} userType - User type (trainer, master_trainer, admin)
     * @param {Object} options - Login options
     */
    async login(userType = 'trainer', options = {}) {
        const user = getUserConfig(userType);
        
        console.log(`🔑 Attempting login as ${userType} (${user.email})`);
        
        // Check if we already have valid authentication
        if (options.forceLogin !== true) {
            try {
                await verifyAuthentication(this.page, userType);
                console.log(`✅ Already authenticated as ${userType}`);
                return;
            } catch {
                // Not authenticated, proceed with login
            }
        }
        
        // Navigate to login page if not already there
        const currentUrl = this.page.url();
        if (!currentUrl.includes('/wp-login.php') && !currentUrl.includes('/training-login/')) {
            await this.navigateToLogin(userType, options);
        }
        
        // Fill login form
        await this.fillLoginForm(user.email, user.password, options);
        
        // Submit and wait for navigation
        await this.submitLoginForm(userType);
        
        // Verify successful login
        await this.verifySuccessfulLogin(userType);
        
        console.log(`✅ Successfully logged in as ${userType}`);
    }
    
    /**
     * Fill login form with credentials
     * @param {string} email - User email
     * @param {string} password - User password
     * @param {Object} options - Fill options
     */
    async fillLoginForm(email, password, options = {}) {
        // Find and fill email field
        const emailField = this.page.locator(this.selectors.generic.email).first();
        await emailField.waitFor({ state: 'visible', timeout: 5000 });
        await emailField.clear();
        await emailField.fill(email);
        
        // Find and fill password field
        const passwordField = this.page.locator(this.selectors.generic.password).first();
        await passwordField.waitFor({ state: 'visible', timeout: 5000 });
        await passwordField.clear();
        await passwordField.fill(password);
        
        // Handle remember me option
        if (options.rememberMe) {
            try {
                const rememberField = this.page.locator('input[name="rememberme"], #rememberme').first();
                if (await rememberField.isVisible()) {
                    await rememberField.check();
                }
            } catch {
                // Remember me field not available, that's fine
            }
        }
        
        // Small delay to ensure form is ready
        await this.page.waitForTimeout(500);
    }
    
    /**
     * Submit login form and wait for navigation
     * @param {string} userType - User type for navigation verification
     */
    async submitLoginForm(userType) {
        const submitButton = this.page.locator(this.selectors.generic.submit).first();
        await submitButton.waitFor({ state: 'visible', timeout: 5000 });
        
        // Wait for navigation after clicking submit
        await Promise.all([
            this.page.waitForURL(url => 
                !url.includes('/wp-login.php') && 
                !url.includes('/training-login/'), 
                { timeout: AUTH_CONFIG.timeout }
            ),
            submitButton.click()
        ]);
        
        // Additional wait for page to fully load
        await this.page.waitForLoadState('networkidle', { timeout: 10000 });
    }
    
    /**
     * Verify successful login and role access
     * @param {string} userType - Expected user type
     */
    async verifySuccessfulLogin(userType) {
        // Check for login errors first
        await this.checkForLoginErrors();
        
        // Verify authentication using helper
        await verifyAuthentication(this.page, userType);
        
        // Additional role-specific verification
        switch (userType) {
            case 'trainer':
                await expect(this.page.locator(this.navigation.trainerDashboard)).toBeVisible({ timeout: 10000 });
                break;
            case 'master_trainer':
                await expect(this.page.locator(this.navigation.masterDashboard)).toBeVisible({ timeout: 10000 });
                break;
            case 'admin':
                await expect(this.page.locator(this.navigation.adminDashboard)).toBeVisible({ timeout: 10000 });
                break;
        }
    }
    
    /**
     * Check for login errors and throw if found
     */
    async checkForLoginErrors() {
        const errorSelectors = [
            this.selectors.wpLogin.error,
            this.selectors.hvacLogin.error,
            '.error, .login-error, .error-message'
        ];
        
        for (const selector of errorSelectors) {
            const errorElement = this.page.locator(selector);
            if (await errorElement.isVisible()) {
                const errorText = await errorElement.textContent();
                throw new Error(`Login failed: ${errorText}`);
            }
        }
    }
    
    /**
     * Login with authentication state management
     * @param {string} userType - User type
     * @param {Object} context - Browser context
     * @param {Object} options - Login options
     */
    async loginWithStateManagement(userType, context, options = {}) {
        // Try to use saved authentication state first
        if (!options.forceLogin) {
            const authStatePath = await getAuthStatePath(userType);
            if (authStatePath) {
                try {
                    console.log(`🔄 Loading saved auth state for ${userType}`);
                    await context.addCookies(require(authStatePath).cookies || []);
                    await verifyAuthentication(this.page, userType);
                    console.log(`✅ Restored authentication for ${userType}`);
                    return;
                } catch (error) {
                    console.log(`⚠️ Saved auth state invalid, performing fresh login`);
                }
            }
        }
        
        // Perform fresh login
        await this.login(userType, options);
        
        // Save authentication state for future use
        try {
            await saveAuthState(userType, context);
        } catch (error) {
            console.warn('Could not save authentication state:', error.message);
        }
    }
    
    /**
     * Logout current user
     */
    async logout() {
        await performLogout(this.page);
    }
    
    /**
     * Quick login helper for common test scenarios
     * @param {string} userType - User type
     * @param {Object} options - Login options
     */
    async quickLogin(userType = 'trainer', options = {}) {
        return this.login(userType, { ...options, skipNavigation: true });
    }
    
    /**
     * Login as trainer (convenience method)
     * @param {Object} options - Login options
     */
    async loginAsTrainer(options = {}) {
        return this.login('trainer', options);
    }
    
    /**
     * Login as master trainer (convenience method)
     * @param {Object} options - Login options
     */
    async loginAsMasterTrainer(options = {}) {
        return this.login('master_trainer', options);
    }
    
    /**
     * Login as admin (convenience method)
     * @param {Object} options - Login options
     */
    async loginAsAdmin(options = {}) {
        return this.login('admin', { ...options, useWpLogin: true });
    }
    
    /**
     * Switch between user roles (logout and login as different user)
     * @param {string} fromUserType - Current user type
     * @param {string} toUserType - Target user type
     */
    async switchUser(fromUserType, toUserType) {
        console.log(`🔄 Switching from ${fromUserType} to ${toUserType}`);
        
        if (fromUserType !== toUserType) {
            await this.logout();
            await this.login(toUserType);
        }
    }
    
    /**
     * Verify current user has expected role access
     * @param {string} expectedUserType - Expected user type
     */
    async verifyCurrentUserRole(expectedUserType) {
        await verifyAuthentication(this.page, expectedUserType);
    }
}

module.exports = LoginPage;