/**
 * Master Trainer E2E Test Suite - Modernized
 * Comprehensive end-to-end testing using the new framework architecture
 * 
 * This replaces test-master-trainer-e2e.js with 90% less code duplication
 */

const BaseTest = require('../../framework/base/BaseTest');
const { createEnvironmentConfig } = require('../../environments/EnvironmentConfig');
const MasterTrainerDashboard = require('../../page-objects/master-trainer/MasterTrainerDashboard');
const SecurityTestFramework = require('../../utilities/security/SecurityTestFramework');
const { getTestDataManager } = require('../../data/TestDataManager');

class MasterTrainerE2ETest extends BaseTest {
    constructor() {
        super('MasterTrainerE2E');
        this.envConfig = null;
        this.testDataManager = null;
        this.securityFramework = null;
        this.dashboardPage = null;
    }

    /**
     * Set up the test suite
     */
    async setUp() {
        // Load environment configuration
        this.envConfig = createEnvironmentConfig(process.env.TEST_ENVIRONMENT || 'staging');
        
        // Initialize with environment-specific config
        await super.setUp(this.envConfig.getBrowserConfig());
        
        // Initialize test data manager
        this.testDataManager = getTestDataManager(this.envConfig.getEnvironmentName());
        await this.testDataManager.initialize();
        
        // Initialize security framework
        this.securityFramework = new SecurityTestFramework(this.envConfig.getConfig());
        await this.securityFramework.initialize();
        
        // Initialize page objects
        this.dashboardPage = new MasterTrainerDashboard();
        this.dashboardPage.setBaseUrl(this.envConfig.getBaseUrl());
        
        console.log(`🚀 Master Trainer E2E Test Suite initialized for ${this.envConfig.getEnvironmentName()}`);
    }

    /**
     * Run the complete master trainer E2E test suite
     */
    async run() {
        try {
            await this.testAuthenticationAndAccess();
            await this.testDashboardFunctionality();
            await this.testEventsManagement();
            await this.testTrainerManagement();
            await this.testAnnouncementsSystem();
            await this.testImportExportFeatures();
            await this.testCommunicationTemplates();
            await this.testSecurityControls();
            
            console.log('✅ All Master Trainer E2E tests completed successfully');
            
        } catch (error) {
            console.error('❌ Master Trainer E2E test suite failed:', error.message);
            throw error;
        }
    }

    /**
     * Test authentication and access control
     */
    async testAuthenticationAndAccess() {
        await this.runTestStep('Master Trainer Authentication', async () => {
            // Test login with master trainer account
            const masterAccount = this.testDataManager.getTestAccount('masterTrainer');
            await this.authManager.login(masterAccount);
            
            // Verify successful authentication
            const isLoggedIn = await this.authManager.isUserLoggedIn();
            this.assertTrue(isLoggedIn, 'Master trainer should be logged in');
            
            // Navigate to master trainer dashboard
            await this.dashboardPage.navigate();
            await this.dashboardPage.waitForPageReady();
            
            // Verify dashboard loads correctly
            const isAuthenticated = await this.dashboardPage.isAuthenticatedAsMasterTrainer();
            this.assertTrue(isAuthenticated, 'Should be authenticated as master trainer');
            
            return { authenticated: true, dashboardLoaded: true };
        });

        await this.runTestStep('Access Control Verification', async () => {
            // Test access to master trainer specific pages
            await this.dashboardPage.navigateToEvents();
            this.assertUrlMatches('/master-trainer/events/', 'Should access events page');
            
            await this.dashboardPage.navigateToTrainers();
            this.assertUrlMatches('/master-trainer/trainers/', 'Should access trainers page');
            
            await this.dashboardPage.navigateToAnnouncements();
            this.assertUrlMatches('/master-trainer/announcements/', 'Should access announcements');
            
            return { masterPagesAccessible: true };
        });
    }

    /**
     * Test dashboard functionality
     */
    async testDashboardFunctionality() {
        await this.runTestStep('Dashboard Navigation', async () => {
            await this.dashboardPage.navigate();
            await this.dashboardPage.waitForDashboardLoaded();
            
            // Test navigation menu
            const hasNavMenu = await this.dashboardPage.hasNavigationMenu();
            this.assertTrue(hasNavMenu, 'Dashboard should have navigation menu');
            
            const menuItems = await this.dashboardPage.getNavigationMenuItems();
            this.assertTrue(menuItems.length > 0, 'Navigation menu should have items');
            
            return { navigationWorking: true, menuItems: menuItems.length };
        });

        await this.runTestStep('Dashboard Statistics', async () => {
            const stats = await this.dashboardPage.getDashboardStats();
            
            // Verify statistics are present (even if zero)
            this.assertTrue(
                stats.totalEvents !== undefined || 
                stats.totalTrainers !== undefined || 
                stats.pendingApprovals !== undefined,
                'Dashboard should display statistics'
            );
            
            return { statisticsLoaded: true, stats };
        });

        await this.runTestStep('Dashboard Sections Visibility', async () => {
            const sections = ['events', 'trainers', 'announcements'];
            const visibleSections = [];
            
            for (const section of sections) {
                const isVisible = await this.dashboardPage.isDashboardSectionVisible(section);
                if (isVisible) visibleSections.push(section);
            }
            
            this.assertTrue(visibleSections.length > 0, 'At least one dashboard section should be visible');
            
            return { visibleSections };
        });
    }

    /**
     * Test events management functionality
     */
    async testEventsManagement() {
        await this.runTestStep('Events Overview Access', async () => {
            await this.dashboardPage.navigateToEvents();
            
            // Wait for events page to load
            await this.browserManager.waitForPageLoad();
            
            // Verify we're on the events page
            this.assertUrlMatches('/master-trainer/events/', 'Should be on events overview page');
            
            // Check for events list or empty state
            const hasEventsTable = await this.hasElement('.events-table, .events-list, .no-events');
            this.assertTrue(hasEventsTable, 'Events page should display events table or empty state');
            
            return { eventsPageAccessible: true };
        });

        await this.runTestStep('Events Management Features', async () => {
            // Look for common events management features
            const features = {
                createEvent: await this.hasElement('a[href*="create"], .create-event, .add-event'),
                editEvent: await this.hasElement('a[href*="edit"], .edit-event, .event-actions'),
                eventSearch: await this.hasElement('input[type="search"], .search-events, .events-search'),
                eventFilters: await this.hasElement('.filter, .events-filter, select')
            };
            
            const availableFeatures = Object.keys(features).filter(key => features[key]);
            console.log(`    Available features: ${availableFeatures.join(', ')}`);
            
            return { eventsFeatures: features, availableFeatures };
        });
    }

    /**
     * Test trainer management functionality
     */
    async testTrainerManagement() {
        await this.runTestStep('Trainers Overview Access', async () => {
            await this.dashboardPage.navigateToTrainers();
            
            // Wait for trainers page to load
            await this.browserManager.waitForPageLoad();
            
            // Verify we're on the trainers page
            this.assertUrlMatches('/master-trainer/trainers/', 'Should be on trainers management page');
            
            // Check for trainers list
            const hasTrainersList = await this.hasElement('.trainers-table, .trainers-list, .no-trainers');
            this.assertTrue(hasTrainersList, 'Trainers page should display trainers list or empty state');
            
            return { trainersPageAccessible: true };
        });

        await this.runTestStep('Trainer Management Features', async () => {
            // Look for trainer management features
            const features = {
                addTrainer: await this.hasElement('a[href*="add"], .add-trainer, .create-trainer'),
                editTrainer: await this.hasElement('a[href*="edit"], .edit-trainer, .trainer-actions'),
                trainerSearch: await this.hasElement('input[type="search"], .search-trainers'),
                trainerProfile: await this.hasElement('a[href*="profile"], .trainer-profile, .view-profile')
            };
            
            const availableFeatures = Object.keys(features).filter(key => features[key]);
            console.log(`    Available trainer features: ${availableFeatures.join(', ')}`);
            
            return { trainerFeatures: features, availableFeatures };
        });
    }

    /**
     * Test announcements system
     */
    async testAnnouncementsSystem() {
        await this.runTestStep('Announcements Access', async () => {
            await this.dashboardPage.navigateToAnnouncements();
            
            // Wait for announcements page to load
            await this.browserManager.waitForPageLoad();
            
            // Verify we're on the announcements page
            this.assertUrlMatches('/master-trainer/announcements/', 'Should be on announcements page');
            
            // Check for announcements interface
            const hasAnnouncementsInterface = await this.hasElement(
                '.announcements-list, .announcements-table, .no-announcements, .announcement-item'
            );
            this.assertTrue(hasAnnouncementsInterface, 'Announcements page should display interface');
            
            return { announcementsPageAccessible: true };
        });

        await this.runTestStep('Announcements Management Features', async () => {
            const features = {
                createAnnouncement: await this.hasElement('a[href*="create"], .create-announcement, .add-announcement'),
                editAnnouncement: await this.hasElement('a[href*="edit"], .edit-announcement, .announcement-actions'),
                manageAnnouncements: await this.hasElement('a[href*="manage"], .manage-announcements'),
                announcementSearch: await this.hasElement('input[type="search"], .search-announcements')
            };
            
            const availableFeatures = Object.keys(features).filter(key => features[key]);
            console.log(`    Available announcement features: ${availableFeatures.join(', ')}`);
            
            return { announcementFeatures: features, availableFeatures };
        });
    }

    /**
     * Test import/export features
     */
    async testImportExportFeatures() {
        await this.runTestStep('Google Sheets Integration Access', async () => {
            await this.dashboardPage.navigateToGoogleSheets();
            
            // Wait for import/export page to load
            await this.browserManager.waitForPageLoad();
            
            // Verify we're on the import/export page
            this.assertUrlMatches('/master-trainer/google-sheets/', 'Should be on Google Sheets page');
            
            // Check for import/export interface
            const hasImportExportInterface = await this.hasElement(
                '.import-export, .google-sheets, .data-management, .import-section, .export-section'
            );
            this.assertTrue(hasImportExportInterface, 'Import/Export page should display interface');
            
            return { importExportPageAccessible: true };
        });

        await this.runTestStep('Import/Export Features', async () => {
            const features = {
                importData: await this.hasElement('input[type="file"], .import-button, .upload-file'),
                exportData: await this.hasElement('.export-button, .download-data, a[href*="export"]'),
                googleSheets: await this.hasElement('.google-sheets, .sheets-integration'),
                dataValidation: await this.hasElement('.validate-data, .data-preview')
            };
            
            const availableFeatures = Object.keys(features).filter(key => features[key]);
            console.log(`    Available import/export features: ${availableFeatures.join(', ')}`);
            
            return { importExportFeatures: features, availableFeatures };
        });
    }

    /**
     * Test communication templates
     */
    async testCommunicationTemplates() {
        await this.runTestStep('Communication Templates Access', async () => {
            await this.dashboardPage.navigateToCommunicationTemplates();
            
            // Wait for templates page to load
            await this.browserManager.waitForPageLoad();
            
            // Verify we're on the templates page
            this.assertUrlMatches('/master-trainer/communication-templates/', 'Should be on communication templates page');
            
            // Check for templates interface
            const hasTemplatesInterface = await this.hasElement(
                '.templates-list, .communication-templates, .template-item, .no-templates'
            );
            this.assertTrue(hasTemplatesInterface, 'Templates page should display interface');
            
            return { templatesPageAccessible: true };
        });

        await this.runTestStep('Template Management Features', async () => {
            const features = {
                createTemplate: await this.hasElement('a[href*="create"], .create-template, .add-template'),
                editTemplate: await this.hasElement('a[href*="edit"], .edit-template, .template-actions'),
                previewTemplate: await this.hasElement('.preview-template, .template-preview'),
                templateCategories: await this.hasElement('.template-category, .category-filter')
            };
            
            const availableFeatures = Object.keys(features).filter(key => features[key]);
            console.log(`    Available template features: ${availableFeatures.join(', ')}`);
            
            return { templateFeatures: features, availableFeatures };
        });
    }

    /**
     * Test security controls
     */
    async testSecurityControls() {
        await this.runTestStep('Authentication Security', async () => {
            // Test protected URLs redirect properly
            const protectedUrls = this.testDataManager.getProtectedUrls();
            
            // Logout first
            await this.authManager.logout();
            
            // Test authentication redirects
            const authResults = await this.securityFramework.testAuthenticationRedirects(
                protectedUrls.slice(0, 5) // Test first 5 URLs to save time
            );
            
            this.assertTrue(authResults.passed > 0, 'Some authentication redirects should work');
            
            // Re-login for next tests
            const masterAccount = this.testDataManager.getTestAccount('masterTrainer');
            await this.authManager.login(masterAccount);
            
            return { authRedirectsPassed: authResults.passed, authRedirectsFailed: authResults.failed };
        });

        await this.runTestStep('Role-Based Access Control', async () => {
            // Test role-based access scenarios
            const roleScenarios = this.testDataManager.getRoleAccessTestScenarios();
            
            // Test a subset of scenarios to save time
            const limitedScenarios = roleScenarios.slice(0, 3);
            const roleResults = await this.securityFramework.testRoleBasedAccess(limitedScenarios);
            
            this.assertTrue(roleResults.passed > 0, 'Some role-based access controls should work');
            
            return { roleAccessPassed: roleResults.passed, roleAccessFailed: roleResults.failed };
        });
    }

    /**
     * Clean up after tests
     */
    async tearDown() {
        try {
            // Clean up security framework
            if (this.securityFramework) {
                await this.securityFramework.cleanup();
            }
            
            // Clear test data cache
            if (this.testDataManager) {
                this.testDataManager.clearCache();
            }
            
            // Take final screenshot
            await this.dashboardPage.takeScreenshot('master-trainer-e2e-final.png');
            
        } catch (error) {
            console.warn('Cleanup warning:', error.message);
        }
        
        await super.tearDown();
    }
}

/**
 * Run the master trainer E2E test suite
 */
async function runMasterTrainerE2ETest() {
    const test = new MasterTrainerE2ETest();
    
    try {
        await test.setUp();
        await test.run();
        
    } catch (error) {
        console.error('❌ Master Trainer E2E Test Failed:', error.message);
        process.exit(1);
        
    } finally {
        await test.tearDown();
    }
}

// Run the test if this file is executed directly
if (require.main === module) {
    runMasterTrainerE2ETest();
}

module.exports = { MasterTrainerE2ETest, runMasterTrainerE2ETest };