/**
 * Authentication Setup and State Management
 * 
 * Provides shared authentication utilities for all HVAC test suites:
 * - Role-based authentication (trainer, master_trainer, admin)
 * - Authentication state storage and reuse
 * - Login/logout helpers
 * - Session management
 * - Security best practices
 * 
 * @package HVAC_Community_Events
 * @version 3.0.0
 * @created 2025-08-20
 */

const { expect } = require('@playwright/test');
const path = require('path');
const fs = require('fs').promises;

// Authentication configuration
const AUTH_CONFIG = {
    baseUrl: process.env.UPSKILL_STAGING_URL || 'https://upskill-staging.measurequick.com',
    loginUrl: '/training-login/',
    wpLoginUrl: '/wp-login.php',
    timeout: 15000,
    storageDir: path.join(__dirname, '../.auth'),
    
    // Test user credentials for different roles
    users: {
        trainer: {
            email: 'test_trainer@example.com',
            password: 'TestTrainer123!',
            role: 'hvac_trainer',
            dashboardPath: '/trainer/dashboard/',
            storageFile: 'trainer-auth.json'
        },
        master_trainer: {
            email: 'test_master@example.com',
            password: 'TestMaster123!',
            role: 'hvac_master_trainer',
            dashboardPath: '/master-trainer/master-dashboard/',
            storageFile: 'master-trainer-auth.json'
        },
        admin: {
            email: 'admin@example.com',
            password: 'AdminTest123!',
            role: 'administrator',
            dashboardPath: '/wp-admin/',
            storageFile: 'admin-auth.json'
        }
    }
};

/**
 * Ensure authentication storage directory exists
 */
async function ensureAuthStorageDir() {
    try {
        await fs.mkdir(AUTH_CONFIG.storageDir, { recursive: true });
    } catch (error) {
        console.warn('Could not create auth storage directory:', error.message);
    }
}

/**
 * Save authentication state to file
 * @param {string} userType - User type (trainer, master_trainer, admin)
 * @param {Object} context - Browser context with authentication
 */
async function saveAuthState(userType, context) {
    await ensureAuthStorageDir();
    
    const user = AUTH_CONFIG.users[userType];
    if (!user) {
        throw new Error(`Unknown user type: ${userType}`);
    }
    
    const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
    
    try {
        await context.storageState({ path: storageFile });
        console.log(`✅ Authentication state saved for ${userType}: ${storageFile}`);
    } catch (error) {
        console.warn(`Could not save auth state for ${userType}:`, error.message);
    }
}

/**
 * Load authentication state from file
 * @param {string} userType - User type (trainer, master_trainer, admin)
 * @returns {string|null} - Path to storage file or null if not exists
 */
async function getAuthStatePath(userType) {
    const user = AUTH_CONFIG.users[userType];
    if (!user) {
        throw new Error(`Unknown user type: ${userType}`);
    }
    
    const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
    
    try {
        await fs.access(storageFile);
        return storageFile;
    } catch {
        return null;
    }
}

/**
 * Clear authentication state for user type
 * @param {string} userType - User type (trainer, master_trainer, admin)
 */
async function clearAuthState(userType = null) {
    await ensureAuthStorageDir();
    
    if (userType) {
        const user = AUTH_CONFIG.users[userType];
        if (user) {
            const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
            try {
                await fs.unlink(storageFile);
                console.log(`🗑️ Cleared auth state for ${userType}`);
            } catch (error) {
                // File doesn't exist, that's fine
            }
        }
    } else {
        // Clear all auth states
        for (const [type, user] of Object.entries(AUTH_CONFIG.users)) {
            const storageFile = path.join(AUTH_CONFIG.storageDir, user.storageFile);
            try {
                await fs.unlink(storageFile);
                console.log(`🗑️ Cleared auth state for ${type}`);
            } catch {
                // File doesn't exist, that's fine
            }
        }
    }
}

/**
 * Verify user is authenticated and has correct role access
 * @param {Page} page - Playwright page object
 * @param {string} userType - Expected user type
 */
async function verifyAuthentication(page, userType) {
    const user = AUTH_CONFIG.users[userType];
    if (!user) {
        throw new Error(`Unknown user type: ${userType}`);
    }
    
    // Navigate to expected dashboard
    await page.goto(`${AUTH_CONFIG.baseUrl}${user.dashboardPath}`, { 
        waitUntil: 'networkidle',
        timeout: AUTH_CONFIG.timeout 
    });
    
    // Verify we're not on login page
    const currentUrl = page.url();
    if (currentUrl.includes('/wp-login.php') || currentUrl.includes('/training-login/')) {
        throw new Error(`Authentication failed for ${userType} - redirected to login`);
    }
    
    // Verify dashboard is accessible
    await expect(page.locator('body')).toBeVisible({ timeout: 5000 });
    
    // Role-specific verification
    switch (userType) {
        case 'trainer':
            await expect(page.locator('text=Dashboard, text=Trainer Dashboard')).toBeVisible({ timeout: 5000 });
            break;
        case 'master_trainer':
            await expect(page.locator('text=Master Dashboard, text=Master Trainer')).toBeVisible({ timeout: 5000 });
            break;
        case 'admin':
            await expect(page.locator('#wpadminbar, .wp-admin')).toBeVisible({ timeout: 5000 });
            break;
    }
    
    console.log(`✅ Authentication verified for ${userType}`);
}

/**
 * Perform login for specified user type
 * @param {Page} page - Playwright page object
 * @param {string} userType - User type (trainer, master_trainer, admin)
 * @param {Object} options - Login options
 */
async function performLogin(page, userType, options = {}) {
    const user = AUTH_CONFIG.users[userType];
    if (!user) {
        throw new Error(`Unknown user type: ${userType}`);
    }
    
    const useWpLogin = options.useWpLogin || userType === 'admin';
    const loginUrl = useWpLogin ? AUTH_CONFIG.wpLoginUrl : AUTH_CONFIG.loginUrl;
    
    console.log(`🔑 Logging in as ${userType} via ${loginUrl}`);
    
    // Navigate to login page
    await page.goto(`${AUTH_CONFIG.baseUrl}${loginUrl}`, { 
        waitUntil: 'networkidle',
        timeout: AUTH_CONFIG.timeout 
    });
    
    // Wait for login form
    await page.waitForSelector('#user_login, input[name="log"], input[type="email"]', { 
        timeout: 10000 
    });
    
    // Fill login form (handle different form structures)
    const emailField = await page.locator('#user_login, input[name="log"], input[type="email"]').first();
    const passwordField = await page.locator('#user_pass, input[name="pwd"], input[type="password"]').first();
    const submitButton = await page.locator('#wp-submit, button[type="submit"], input[type="submit"]').first();
    
    await emailField.fill(user.email);
    await passwordField.fill(user.password);
    
    // Submit form and wait for navigation
    await Promise.all([
        page.waitForURL(url => !url.includes('/wp-login.php') && !url.includes('/training-login/'), { 
            timeout: AUTH_CONFIG.timeout 
        }),
        submitButton.click()
    ]);
    
    // Verify login was successful
    await verifyAuthentication(page, userType);
    
    console.log(`✅ Login successful for ${userType}`);
}

/**
 * Logout current user
 * @param {Page} page - Playwright page object
 */
async function performLogout(page) {
    try {
        // Try different logout methods
        const logoutSelectors = [
            'a[href*="wp-login.php?action=logout"]',
            'a[href*="logout"]',
            'text=Logout',
            'text=Log Out',
            '#wp-admin-bar-logout a'
        ];
        
        for (const selector of logoutSelectors) {
            const logoutLink = await page.locator(selector).first();
            if (await logoutLink.isVisible()) {
                await logoutLink.click();
                await page.waitForLoadState('networkidle');
                break;
            }
        }
        
        console.log('✅ Logout completed');
    } catch (error) {
        console.warn('Logout may have failed:', error.message);
    }
}

/**
 * Get user configuration for specified type
 * @param {string} userType - User type
 * @returns {Object} User configuration
 */
function getUserConfig(userType) {
    const user = AUTH_CONFIG.users[userType];
    if (!user) {
        throw new Error(`Unknown user type: ${userType}`);
    }
    return { ...user };
}

/**
 * Get all available user types
 * @returns {string[]} Array of user types
 */
function getAvailableUserTypes() {
    return Object.keys(AUTH_CONFIG.users);
}

module.exports = {
    AUTH_CONFIG,
    ensureAuthStorageDir,
    saveAuthState,
    getAuthStatePath,
    clearAuthState,
    verifyAuthentication,
    performLogin,
    performLogout,
    getUserConfig,
    getAvailableUserTypes
};