/**
 * Event Manager Consolidation Test Suite
 * 
 * Tests the new unified HVAC_Event_Manager that replaces 8+ fragmented implementations:
 * - Event CRUD operations through single API
 * - Template routing and loading
 * - Form submission workflows  
 * - TEC integration validation
 * - Security and role validation
 * - Memory-efficient data loading
 * 
 * @package HVAC_Community_Events
 * @version 3.0.0
 * @created 2025-08-20
 */

const { test, expect, authHelpers, LoginPage } = require('../helpers/auth-fixtures');
const path = require('path');

// Test configuration
const BASE_URL = process.env.UPSKILL_STAGING_URL || 'https://upskill-staging.measurequick.com';
const TEST_TIMEOUT = 90000;

// Test event data
const TEST_EVENT_DATA = {
    title: `Unified Event Manager Test ${Date.now()}`,
    description: 'Test event created through unified HVAC_Event_Manager system',
    startDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
    endDate: new Date(Date.now() + 8 * 24 * 60 * 60 * 1000),
    venue: 'Test Training Facility',
    organizer: 'Test Training Org',
    category: 'HVAC Training',
    cost: '299.00'
};

// Helper functions - using new authentication system
async function loginAsUser(page, userType = 'trainer') {
    await authHelpers.loginAs(page, userType);
}

async function createTestEvent(page, eventData = TEST_EVENT_DATA) {
    await page.goto(`${BASE_URL}/trainer/events/create/`);
    
    // Wait for form to load (could be iframe or direct form)
    await page.waitForSelector('.hvac-event-form-wrapper, iframe#tec-create-frame, form', { timeout: 10000 });
    
    // Determine form context (iframe vs direct)
    const iframe = await page.$('iframe#tec-create-frame');
    const context = iframe ? await iframe.contentFrame() : page;
    
    if (!context) {
        throw new Error('Could not access form context');
    }
    
    // Fill event details using unified form handling
    await context.fill('input[name="post_title"], #tribe-events-title', eventData.title);
    
    // Handle description field (TinyMCE or textarea)
    const descField = await context.$('#content, textarea[name="post_content"], .wp-editor-area');
    if (descField) {
        await descField.fill(eventData.description);
    }
    
    // Set event dates
    const startDateField = await context.$('input[name="EventStartDate"], #EventStartDate, [data-field="start-date"]');
    if (startDateField) {
        await startDateField.fill(eventData.startDate.toISOString().split('T')[0]);
    }
    
    const endDateField = await context.$('input[name="EventEndDate"], #EventEndDate, [data-field="end-date"]');
    if (endDateField) {
        await endDateField.fill(eventData.endDate.toISOString().split('T')[0]);
    }
    
    // Add venue information
    const venueField = await context.$('input[name="venue[Venue]"], #venue-name, [data-field="venue"]');
    if (venueField) {
        await venueField.fill(eventData.venue);
    }
    
    // Add organizer information
    const organizerField = await context.$('input[name="organizer[Organizer]"], #organizer-name, [data-field="organizer"]');
    if (organizerField) {
        await organizerField.fill(eventData.organizer);
    }
    
    // Submit the form
    const submitButton = await context.$('button[type="submit"], input[type="submit"], .tribe-submit, [data-action="submit"]');
    if (submitButton) {
        await submitButton.click();
    }
    
    // Wait for submission processing
    await page.waitForTimeout(3000);
    
    return eventData;
}

async function getEventList(page) {
    await page.goto(`${BASE_URL}/trainer/events/`);
    await page.waitForSelector('.hvac-events-list, .tribe-events-list, table, .event-item', { timeout: 10000 });
    
    const events = await page.evaluate(() => {
        const eventElements = document.querySelectorAll('.event-item, tr[data-event-id], .hvac-event-row');
        return Array.from(eventElements).map(el => {
            return {
                title: el.querySelector('.event-title, .title, h3, h4')?.textContent?.trim(),
                id: el.getAttribute('data-event-id') || el.getAttribute('data-id'),
                editLink: el.querySelector('a[href*="edit"], .edit-link')?.href
            };
        });
    });
    
    return events;
}

async function deleteTestEvent(page, eventTitle) {
    const events = await getEventList(page);
    const testEvent = events.find(e => e.title?.includes(eventTitle));
    
    if (testEvent && testEvent.editLink) {
        await page.goto(testEvent.editLink);
        
        // Look for delete button in edit form
        const deleteButton = await page.$('button[data-action="delete"], .delete-event, a[href*="delete"]');
        if (deleteButton) {
            await deleteButton.click();
            await page.waitForTimeout(2000);
        }
    }
}

async function takeTestScreenshot(page, name) {
    const screenshotDir = path.join(__dirname, '../../screenshots/event-manager');
    await require('fs').promises.mkdir(screenshotDir, { recursive: true });
    await page.screenshot({ 
        path: path.join(screenshotDir, `${name}-${Date.now()}.png`),
        fullPage: true 
    });
}

test.describe('Event Manager Consolidation Tests', () => {
    test.setTimeout(TEST_TIMEOUT);
    
    test.beforeEach(async ({ page }) => {
        await page.setViewportSize({ width: 1280, height: 720 });
        // Login before each test to ensure authenticated access
        await authHelpers.loginAs(page, 'trainer');
    });

    test.describe('Unified Event Manager API Tests', () => {
        test('should handle event creation through single interface', async ({ page }) => {
            const eventData = await createTestEvent(page);
            
            // Verify event was created
            await page.waitForTimeout(5000);
            const currentUrl = page.url();
            const isSuccess = currentUrl.includes('success') || 
                             currentUrl.includes('events') ||
                             currentUrl.includes('dashboard');
            
            expect(isSuccess).toBeTruthy();
            await takeTestScreenshot(page, 'event-created-unified');
            
            // Cleanup
            await deleteTestEvent(page, eventData.title);
        });

        test('should validate event manager singleton pattern', async ({ page }) => {
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Check for duplicate initialization issues
            const duplicateErrors = await page.evaluate(() => {
                return window.console.logs?.filter(log => 
                    log.includes('duplicate') || 
                    log.includes('already initialized')
                ) || [];
            });
            
            expect(duplicateErrors.length).toBe(0);
        });

        test('should use memory-efficient data loading', async ({ page, browserName }) => {
            test.skip(browserName !== 'chromium', 'Memory testing requires Chromium');
            
            const initialMemory = await page.evaluate(() => {
                return performance.memory ? performance.memory.usedJSHeapSize : 0;
            });
            
            // Load event list (should use generator-based loading)
            await page.goto(`${BASE_URL}/trainer/events/`);
            await page.waitForLoadState('networkidle');
            
            const afterListMemory = await page.evaluate(() => {
                return performance.memory ? performance.memory.usedJSHeapSize : 0;
            });
            
            // Load event creation form
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            await page.waitForLoadState('networkidle');
            
            const afterFormMemory = await page.evaluate(() => {
                return performance.memory ? performance.memory.usedJSHeapSize : 0;
            });
            
            const memoryIncrease = (afterFormMemory - initialMemory) / 1024 / 1024; // MB
            console.log(`Memory increase during event operations: ${memoryIncrease.toFixed(2)}MB`);
            
            // Should not exceed 50MB increase for event operations
            expect(memoryIncrease).toBeLessThan(50);
        });

        test('should handle concurrent event operations', async ({ browser }) => {
            const contexts = await Promise.all([
                browser.newContext(),
                browser.newContext()
            ]);
            
            const pages = await Promise.all(contexts.map(ctx => ctx.newPage()));
            
            // Simulate concurrent event creation - each needs its own login
            const eventPromises = pages.map(async (page, index) => {
                await authHelpers.loginAs(page, 'trainer');
                
                const eventData = {
                    ...TEST_EVENT_DATA,
                    title: `Concurrent Event ${index} ${Date.now()}`
                };
                
                return createTestEvent(page, eventData);
            });
            
            const results = await Promise.all(eventPromises);
            
            // Both events should be created successfully
            expect(results.length).toBe(2);
            results.forEach(result => {
                expect(result.title).toBeTruthy();
            });
            
            // Cleanup
            await Promise.all(contexts.map(ctx => ctx.close()));
        });
    });

    test.describe('Template Routing and Loading Tests', () => {
        test('should route to correct templates based on URL', async ({ page }) => {
            const routes = [
                { url: '/trainer/events/', template: 'events-list' },
                { url: '/trainer/events/create/', template: 'event-create' },
                { url: '/trainer/dashboard/', template: 'dashboard' }
            ];
            
            for (const route of routes) {
                await page.goto(`${BASE_URL}${route.url}`);
                await page.waitForLoadState('domcontentloaded');
                
                // Check for template-specific elements
                const hasTemplateElements = await page.evaluate(() => {
                    return document.querySelector('.hvac-page-wrapper, .hvac-template, main') !== null;
                });
                
                expect(hasTemplateElements).toBeTruthy();
                console.log(`Template routing working for ${route.url}`);
            }
        });

        test('should load templates with proper WordPress integration', async ({ page }) => {
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Check for WordPress template elements
            const wordpressElements = await page.evaluate(() => {
                return {
                    hasHeader: !!document.querySelector('header, .site-header'),
                    hasFooter: !!document.querySelector('footer, .site-footer'),
                    hasNavigation: !!document.querySelector('nav, .navigation, .hvac-nav'),
                    hasWordPressBody: document.body.className.includes('wp-')
                };
            });
            
            expect(wordpressElements.hasHeader).toBeTruthy();
            expect(wordpressElements.hasFooter).toBeTruthy();
            expect(wordpressElements.hasNavigation).toBeTruthy();
            
            await takeTestScreenshot(page, 'template-wordpress-integration');
        });

        test('should handle template fallbacks gracefully', async ({ page }) => {
            // Try to access a non-existent event edit page
            await page.goto(`${BASE_URL}/trainer/events/edit/99999/`);
            
            // Should either redirect or show error page, not crash
            await page.waitForTimeout(3000);
            
            const pageContent = await page.evaluate(() => {
                return {
                    hasErrorMessage: !!document.querySelector('.error, .not-found, .hvac-error'),
                    bodyText: document.body.textContent
                };
            });
            
            // Should handle gracefully without server error
            expect(pageContent.bodyText).not.toContain('Fatal error');
            expect(pageContent.bodyText).not.toContain('500 Internal Server Error');
        });
    });

    test.describe('Form Submission Workflow Tests', () => {
        test('should process form submissions with proper validation', async ({ page }) => {
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Try to submit empty form (should trigger validation)
            const iframe = await page.$('iframe#tec-create-frame');
            const context = iframe ? await iframe.contentFrame() : page;
            
            const submitButton = await context.$('button[type="submit"], input[type="submit"]');
            if (submitButton) {
                await submitButton.click();
                await page.waitForTimeout(2000);
                
                // Check for validation messages
                const hasValidation = await context.evaluate(() => {
                    return !!document.querySelector('.error, .validation-error, .required-field-error');
                });
                
                // Should have validation for required fields
                console.log('Form validation triggered:', hasValidation);
            }
        });

        test('should maintain form state during submission', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            const iframe = await page.$('iframe#tec-create-frame');
            const context = iframe ? await iframe.contentFrame() : page;
            
            // Fill partial form data
            const testTitle = `State Test Event ${Date.now()}`;
            await context.fill('input[name="post_title"], #tribe-events-title', testTitle);
            
            // Trigger form interaction (but don't submit)
            const descField = await context.$('#content, textarea[name="post_content"]');
            if (descField) {
                await descField.fill('Test description');
                await descField.blur(); // Trigger save/state management
            }
            
            await page.waitForTimeout(1000);
            
            // Check if title is still there
            const titleValue = await context.inputValue('input[name="post_title"], #tribe-events-title');
            expect(titleValue).toBe(testTitle);
        });

        test('should handle submission errors gracefully', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Create event with invalid data to trigger error
            const iframe = await page.$('iframe#tec-create-frame');
            const context = iframe ? await iframe.contentFrame() : page;
            
            // Fill with problematic data
            await context.fill('input[name="post_title"], #tribe-events-title', 'X'); // Too short
            
            const submitButton = await context.$('button[type="submit"], input[type="submit"]');
            if (submitButton) {
                await submitButton.click();
                await page.waitForTimeout(3000);
                
                // Should show error message, not crash
                const hasError = await page.evaluate(() => {
                    return !document.body.textContent.includes('Fatal error') &&
                           !document.body.textContent.includes('500 Internal Server Error');
                });
                
                expect(hasError).toBeTruthy();
            }
        });
    });

    test.describe('TEC Integration Validation Tests', () => {
        test('should integrate with The Events Calendar plugin', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Check for TEC-specific elements
            const tecIntegration = await page.evaluate(() => {
                return {
                    hasFrame: !!document.querySelector('iframe#tec-create-frame'),
                    hasTecClasses: document.body.className.includes('tribe') || 
                                   !!document.querySelector('[class*="tribe"]'),
                    hasTecScripts: !!document.querySelector('script[src*="tribe"]')
                };
            });
            
            // Should have some TEC integration
            const hasIntegration = tecIntegration.hasFrame || 
                                  tecIntegration.hasTecClasses || 
                                  tecIntegration.hasTecScripts;
            
            expect(hasIntegration).toBeTruthy();
            console.log('TEC integration detected:', tecIntegration);
        });

        test('should map form fields correctly for TEC', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            const eventData = await createTestEvent(page);
            
            // Verify event appears in events list
            const events = await getEventList(page);
            const createdEvent = events.find(e => e.title?.includes(eventData.title.split(' ')[0]));
            
            expect(createdEvent).toBeTruthy();
            console.log('Event created and found in list:', createdEvent?.title);
            
            // Cleanup
            if (createdEvent) {
                await deleteTestEvent(page, eventData.title);
            }
        });

        test('should handle TEC plugin dependencies', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/`);
            
            // Check if TEC is properly loaded
            const tecStatus = await page.evaluate(() => {
                return {
                    hasTecGlobal: typeof window.tribe !== 'undefined',
                    hasEventElements: !!document.querySelector('.tribe-events, .hvac-events, [data-event]'),
                    hasNoTecErrors: !document.body.textContent.includes('TEC plugin not found')
                };
            });
            
            expect(tecStatus.hasNoTecErrors).toBeTruthy();
            console.log('TEC dependency status:', tecStatus);
        });
    });

    test.describe('Role-Based Access Control Tests', () => {
        test('should enforce trainer role permissions', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            // Trainer should access their own events
            await page.goto(`${BASE_URL}/trainer/events/`);
            await expect(page.locator('.hvac-events-list, .tribe-events-list, table')).toBeVisible();
            
            // Should not access master trainer pages
            await page.goto(`${BASE_URL}/master-trainer/master-dashboard/`);
            const hasAccess = await page.evaluate(() => {
                return !document.body.textContent.includes('Access denied') &&
                       !document.body.textContent.includes('Insufficient permissions');
            });
            
            // Regular trainer should not access master trainer pages
            // (This might redirect or show access denied)
            console.log('Trainer access to master dashboard:', hasAccess);
        });

        test('should enforce master trainer permissions', async ({ page }) => {
            try {
                await loginAsUser(page, 'masterTrainer');
                
                // Master trainer should access both trainer and master pages
                await page.goto(`${BASE_URL}/master-trainer/master-dashboard/`);
                await expect(page.locator('.hvac-master-dashboard, .hvac-dashboard')).toBeVisible();
                
                await page.goto(`${BASE_URL}/trainer/events/`);
                await expect(page.locator('.hvac-events-list, .tribe-events-list, table')).toBeVisible();
                
            } catch (error) {
                console.log('Master trainer test skipped - user may not exist');
            }
        });

        test('should validate nonce security for form submissions', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/create/`);
            
            // Check for nonce fields in forms
            const hasNonce = await page.evaluate(() => {
                const nonceFields = document.querySelectorAll('input[name*="nonce"], input[name*="_token"]');
                return nonceFields.length > 0;
            });
            
            expect(hasNonce).toBeTruthy();
            console.log('Nonce security fields found');
        });
    });

    test.describe('Event Lifecycle Management Tests', () => {
        test('should complete full event CRUD cycle', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            
            // CREATE
            const originalData = await createTestEvent(page);
            await takeTestScreenshot(page, 'event-created');
            
            // READ
            const events = await getEventList(page);
            const createdEvent = events.find(e => e.title?.includes(originalData.title.split(' ')[0]));
            expect(createdEvent).toBeTruthy();
            
            // UPDATE (if edit link available)
            if (createdEvent && createdEvent.editLink) {
                await page.goto(createdEvent.editLink);
                await page.waitForTimeout(3000);
                
                const iframe = await page.$('iframe');
                const context = iframe ? await iframe.contentFrame() : page;
                
                const titleField = await context.$('input[name="post_title"], #tribe-events-title');
                if (titleField) {
                    const updatedTitle = `Updated ${originalData.title}`;
                    await titleField.fill(updatedTitle);
                    
                    const submitButton = await context.$('button[type="submit"], input[type="submit"]');
                    if (submitButton) {
                        await submitButton.click();
                        await page.waitForTimeout(3000);
                    }
                }
                
                await takeTestScreenshot(page, 'event-updated');
            }
            
            // DELETE (cleanup)
            await deleteTestEvent(page, originalData.title);
        });

        test('should handle event list pagination and filtering', async ({ page }) => {
            await loginAsUser(page, 'trainer');
            await page.goto(`${BASE_URL}/trainer/events/`);
            
            // Check for pagination controls
            const paginationExists = await page.evaluate(() => {
                return !!document.querySelector('.pagination, .page-numbers, .nav-links');
            });
            
            // Check for filter controls
            const filterExists = await page.evaluate(() => {
                return !!document.querySelector('.event-filter, select[name*="filter"], input[name*="search"]');
            });
            
            console.log('Event list features - Pagination:', paginationExists, 'Filters:', filterExists);
        });
    });
});

// Export event manager test configuration
module.exports = {
    testDir: __dirname,
    timeout: TEST_TIMEOUT,
    retries: 1,
    workers: 1, // Sequential for event operations
    use: {
        baseURL: BASE_URL,
        screenshot: 'only-on-failure',
        video: 'retain-on-failure',
        trace: 'on-first-retry'
    }
};