/**
 * Authentication Manager - Centralized authentication handling
 * Manages all user login/logout scenarios and role-based authentication
 */

const { getBrowserManager } = require('../browser/BrowserManager');
const BasePage = require('../base/BasePage');

class AuthManager {
    constructor() {
        this.currentUser = null;
        this.isLoggedIn = false;
        this.browserManager = null;
        this.loginPage = null;
        this.config = null;
    }

    /**
     * Initialize authentication manager
     * @param {Object} config - Configuration object
     * @returns {Promise<void>}
     */
    async initialize(config = {}) {
        this.config = {
            baseUrl: 'https://upskill-staging.measurequick.com',
            loginPath: '/community-login/',
            logoutPath: '/wp-login.php?action=logout',
            ...config
        };

        this.browserManager = getBrowserManager();
        this.loginPage = new LoginPage();
    }

    /**
     * Login with user credentials
     * @param {Object} user - User credentials
     * @param {Object} options - Login options
     * @returns {Promise<void>}
     */
    async login(user, options = {}) {
        const loginOptions = {
            verifySuccess: true,
            takeScreenshot: false,
            ...options
        };

        console.log(`🔐 Logging in as ${user.username} (${user.role || 'unknown role'})`);

        try {
            // Navigate to login page
            await this.loginPage.navigate();
            
            // Fill login form
            await this.loginPage.fillLoginForm(user.username, user.password);
            
            // Submit form
            await this.loginPage.submitLogin();
            
            // Wait for redirect and verify login success
            if (loginOptions.verifySuccess) {
                await this.verifyLoginSuccess(user);
            }
            
            this.currentUser = user;
            this.isLoggedIn = true;
            
            if (loginOptions.takeScreenshot) {
                await this.browserManager.takeScreenshot(`login-success-${user.username}.png`);
            }
            
            console.log(`  ✅ Successfully logged in as ${user.username}`);
            
        } catch (error) {
            console.error(`  ❌ Login failed for ${user.username}: ${error.message}`);
            throw error;
        }
    }

    /**
     * Logout current user
     * @param {Object} options - Logout options
     * @returns {Promise<void>}
     */
    async logout(options = {}) {
        const logoutOptions = {
            verifySuccess: true,
            ...options
        };

        if (!this.isLoggedIn) {
            console.log('  ℹ️  No user logged in');
            return;
        }

        console.log(`🔓 Logging out ${this.currentUser?.username || 'current user'}`);

        try {
            const page = this.browserManager.getCurrentPage();
            
            // Try to find and click logout link
            const logoutSelectors = [
                'a[href*="wp-login.php?action=logout"]',
                'a[href*="logout"]',
                '.logout-link',
                '#wp-admin-bar-logout a'
            ];

            let loggedOut = false;
            for (const selector of logoutSelectors) {
                try {
                    await page.waitForSelector(selector, { timeout: 5000 });
                    await page.click(selector);
                    loggedOut = true;
                    break;
                } catch (error) {
                    // Try next selector
                    continue;
                }
            }

            // Fallback: navigate to logout URL directly
            if (!loggedOut) {
                const logoutUrl = this.config.baseUrl + this.config.logoutPath;
                await page.goto(logoutUrl);
            }

            // Wait for logout confirmation
            if (logoutOptions.verifySuccess) {
                await this.verifyLogoutSuccess();
            }

            this.currentUser = null;
            this.isLoggedIn = false;
            
            console.log('  ✅ Successfully logged out');
            
        } catch (error) {
            console.error(`  ❌ Logout failed: ${error.message}`);
            this.currentUser = null;
            this.isLoggedIn = false;
        }
    }

    /**
     * Quick login for master trainer role
     * @param {Object} options - Login options
     * @returns {Promise<void>}
     */
    async loginAsMasterTrainer(options = {}) {
        const masterUser = this.getMasterTrainerAccount();
        await this.login(masterUser, options);
    }

    /**
     * Quick login for regular trainer role
     * @param {Object} options - Login options
     * @returns {Promise<void>}
     */
    async loginAsTrainer(options = {}) {
        const trainerUser = this.getTrainerAccount();
        await this.login(trainerUser, options);
    }

    /**
     * Verify that login was successful
     * @param {Object} user - User that attempted login
     * @returns {Promise<void>}
     */
    async verifyLoginSuccess(user) {
        const page = this.browserManager.getCurrentPage();
        
        // Wait for redirect away from login page
        try {
            await page.waitForURL(url => !url.includes('community-login'), { timeout: 15000 });
        } catch (error) {
            throw new Error('Login failed - still on login page');
        }

        // Look for logged-in indicators
        const loggedInSelectors = [
            'body.logged-in',
            '#wpadminbar',
            '.dashboard-navigation',
            '[data-user-role]'
        ];

        let loginConfirmed = false;
        for (const selector of loggedInSelectors) {
            try {
                await page.waitForSelector(selector, { timeout: 10000 });
                loginConfirmed = true;
                break;
            } catch (error) {
                continue;
            }
        }

        if (!loginConfirmed) {
            throw new Error('Login success could not be verified');
        }

        // Verify user role if specified
        if (user.role) {
            await this.verifyUserRole(user.role);
        }
    }

    /**
     * Verify that logout was successful
     * @returns {Promise<void>}
     */
    async verifyLogoutSuccess() {
        const page = this.browserManager.getCurrentPage();
        
        try {
            // Wait for logout indicators
            await Promise.race([
                page.waitForURL(url => url.includes('community-login')),
                page.waitForURL(url => url.includes('wp-login')),
                page.waitForSelector('body:not(.logged-in)', { timeout: 10000 })
            ]);
        } catch (error) {
            throw new Error('Logout success could not be verified');
        }
    }

    /**
     * Verify user has expected role
     * @param {string} expectedRole - Expected user role
     * @returns {Promise<void>}
     */
    async verifyUserRole(expectedRole) {
        const page = this.browserManager.getCurrentPage();
        
        try {
            // Check for role-specific elements or attributes
            const roleSelectors = {
                'master_trainer': [
                    '[data-user-role*="master"]',
                    '.master-trainer-dashboard',
                    'a[href*="master-trainer"]'
                ],
                'hvac_trainer': [
                    '[data-user-role*="trainer"]',
                    '.trainer-dashboard',
                    'a[href*="trainer/dashboard"]'
                ]
            };

            const selectors = roleSelectors[expectedRole] || [];
            let roleConfirmed = false;

            for (const selector of selectors) {
                try {
                    await page.waitForSelector(selector, { timeout: 5000 });
                    roleConfirmed = true;
                    break;
                } catch (error) {
                    continue;
                }
            }

            if (!roleConfirmed) {
                console.warn(`Could not verify user role: ${expectedRole}`);
            }
        } catch (error) {
            console.warn(`Role verification failed: ${error.message}`);
        }
    }

    /**
     * Check if user is currently logged in
     * @returns {Promise<boolean>}
     */
    async isUserLoggedIn() {
        try {
            const page = this.browserManager.getCurrentPage();
            const loggedIn = await page.$('body.logged-in, #wpadminbar') !== null;
            this.isLoggedIn = loggedIn;
            return loggedIn;
        } catch (error) {
            return false;
        }
    }

    /**
     * Get current user information
     * @returns {Object|null}
     */
    getCurrentUser() {
        return this.currentUser;
    }

    /**
     * Get master trainer account credentials
     * @returns {Object}
     */
    getMasterTrainerAccount() {
        return {
            username: 'test_master',
            password: 'TestMaster123!',
            email: 'test_master@example.com',
            role: 'master_trainer'
        };
    }

    /**
     * Get alternative master trainer account
     * @returns {Object}
     */
    getAlternateMasterTrainerAccount() {
        return {
            username: 'JoeMedosch@gmail.com',
            password: 'JoeTrainer2025@',
            email: 'JoeMedosch@gmail.com',
            role: 'master_trainer'
        };
    }

    /**
     * Get regular trainer account credentials
     * @returns {Object}
     */
    getTrainerAccount() {
        return {
            username: 'test_trainer',
            password: 'TestTrainer123!',
            email: 'test_trainer@example.com',
            role: 'hvac_trainer'
        };
    }

    /**
     * Clean up authentication state
     * @returns {Promise<void>}
     */
    async cleanup() {
        if (this.isLoggedIn) {
            await this.logout({ verifySuccess: false });
        }
        this.currentUser = null;
        this.isLoggedIn = false;
    }
}

/**
 * Login Page Object - Handles login page interactions
 */
class LoginPage extends BasePage {
    constructor() {
        super();
        this.url = '';
        this.selectors = {
            usernameField: '#user_login, [name="log"], input[type="text"]',
            passwordField: '#user_pass, [name="pwd"], input[type="password"]',
            loginButton: '#wp-submit, [name="wp-submit"], input[type="submit"], button[type="submit"]',
            loginForm: '#loginform, .login-form, form[name="loginform"]',
            errorMessage: '.login_error, .error, .notice-error'
        };
    }

    /**
     * Set login page URL based on environment
     * @param {string} baseUrl - Base URL
     * @param {string} loginPath - Login path
     */
    setLoginUrl(baseUrl, loginPath) {
        this.url = baseUrl + loginPath;
    }

    /**
     * Fill login form with credentials
     * @param {string} username - Username
     * @param {string} password - Password
     * @returns {Promise<void>}
     */
    async fillLoginForm(username, password) {
        await this.waitForElement(this.selectors.usernameField);
        await this.fillField(this.selectors.usernameField, username);
        await this.fillField(this.selectors.passwordField, password);
    }

    /**
     * Submit login form
     * @returns {Promise<void>}
     */
    async submitLogin() {
        await this.clickElement(this.selectors.loginButton);
    }

    /**
     * Check for login errors
     * @returns {Promise<string|null>}
     */
    async getLoginError() {
        try {
            const errorElement = await this.page.$(this.selectors.errorMessage);
            if (errorElement) {
                return await errorElement.textContent();
            }
        } catch (error) {
            // No error message found
        }
        return null;
    }

    /**
     * Set base URL for navigation
     * @param {string} baseUrl - Base URL
     */
    setBaseUrl(baseUrl) {
        this.url = baseUrl + '/community-login/';
    }
}

// Singleton instance
let authManager = null;

/**
 * Get singleton AuthManager instance
 * @returns {AuthManager}
 */
function getAuthManager() {
    if (!authManager) {
        authManager = new AuthManager();
    }
    return authManager;
}

module.exports = { AuthManager, getAuthManager, LoginPage };