/**
 * Registration Full Flow Validation Test
 * Tests the complete registration process including:
 * - Form validation (minlength, pattern, required fields)
 * - Password strength indicator
 * - Password mismatch detection
 * - Successful registration flow
 * CI-compatible: Works in both local and CI environments
 */

const puppeteer = require('puppeteer');
const AuthHelper = require('./auth_helper');
const { getPuppeteerLaunchOptions, takeScreenshot } = require('./puppeteer_config');
const fs = require('fs');
const path = require('path');

// NAVIGATION NOTE: Using 'domcontentloaded' instead of 'networkidle2' for page.goto()
// because networkidle2 waits for no network activity for 500ms, but WebSocket
// connections and background polling keep the network active, causing infinite hangs.
// See: test_login_validation.js and auth_helper.js for detailed explanation.
async function testRegisterFullFlow() {
    const isCI = !!process.env.CI;
    console.log(`🧪 Running registration full flow test (CI mode: ${isCI})`);

    // Create screenshots directory if it doesn't exist
    const screenshotsDir = path.join(__dirname, 'screenshots');
    if (!fs.existsSync(screenshotsDir)) {
        fs.mkdirSync(screenshotsDir, { recursive: true });
    }

    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
    const page = await browser.newPage();
    const baseUrl = 'http://127.0.0.1:5000';

    // Increase default timeout in CI
    if (isCI) {
        page.setDefaultTimeout(60000);
        page.setDefaultNavigationTimeout(60000);
    }

    let testsPassed = 0;
    let testsFailed = 0;

    console.log('🧪 Starting registration full flow tests...\n');

    try {
        // Navigate to register page
        console.log('📄 Navigating to registration page...');
        await page.goto(`${baseUrl}/auth/register`, {
            waitUntil: 'domcontentloaded',
            timeout: 30000
        });

        await page.waitForSelector('input[name="username"]', { timeout: 10000 });
        console.log('✅ Registration page loaded\n');

        // Test 1: Username too short validation
        console.log('📋 Test 1: Username too short (< 3 chars)');
        const usernameInput = await page.$('input[name="username"]');

        await page.type('input[name="username"]', 'ab', { delay: 50 });

        let validity = await page.evaluate(el => ({
            valid: el.validity.valid,
            tooShort: el.validity.tooShort,
            valueMissing: el.validity.valueMissing
        }), usernameInput);

        console.log(`   Value: "ab" (2 chars), tooShort: ${validity.tooShort}`);

        if (validity.tooShort) {
            console.log('✅ Username too short correctly triggers tooShort validity');
            testsPassed++;
        } else {
            console.log('❌ Username too short should trigger tooShort validity');
            testsFailed++;
        }

        // Clear and test with 3 chars (should be valid)
        await page.evaluate(() => document.querySelector('input[name="username"]').value = '');
        await page.type('input[name="username"]', 'abc', { delay: 50 });

        validity = await page.evaluate(el => ({
            valid: el.validity.valid,
            tooShort: el.validity.tooShort
        }), usernameInput);

        console.log(`   Value: "abc" (3 chars), tooShort: ${validity.tooShort}`);

        if (!validity.tooShort) {
            console.log('✅ Username with 3 chars passes minlength check');
            testsPassed++;
        } else {
            console.log('❌ Username with 3 chars should pass minlength check');
            testsFailed++;
        }

        // Test 2: Password too short validation
        console.log('\n📋 Test 2: Password too short (< 8 chars)');
        const passwordInput = await page.$('input[name="password"]');

        await page.type('input[name="password"]', 'short', { delay: 50 });

        validity = await page.evaluate(el => ({
            valid: el.validity.valid,
            tooShort: el.validity.tooShort
        }), passwordInput);

        console.log(`   Value: "short" (5 chars), tooShort: ${validity.tooShort}`);

        if (validity.tooShort) {
            console.log('✅ Password too short correctly triggers tooShort validity');
            testsPassed++;
        } else {
            console.log('❌ Password too short should trigger tooShort validity');
            testsFailed++;
        }

        // Test 3: Password strength indicator
        console.log('\n📋 Test 3: Password strength indicator');

        // Clear password
        await page.evaluate(() => document.querySelector('input[name="password"]').value = '');

        // Test weak password (only lowercase, < 8 chars doesn't count)
        await page.type('input[name="password"]', 'weakpass', { delay: 50 });
        await new Promise(resolve => setTimeout(resolve, 200));

        let strengthBar = await page.$('#password-strength');
        let strengthVisible = await page.evaluate(el => el.style.display !== 'none', strengthBar);
        let strengthClasses = await page.evaluate(el => el.className, strengthBar);

        console.log(`   Weak password "weakpass" - visible: ${strengthVisible}, classes: "${strengthClasses}"`);

        if (strengthVisible) {
            console.log('✅ Password strength indicator is visible');
            testsPassed++;
        } else {
            console.log('❌ Password strength indicator should be visible');
            testsFailed++;
        }

        // Check for correct CSS class (should be ldr-strength-weak)
        if (strengthClasses.includes('ldr-strength-weak')) {
            console.log('✅ Weak password shows weak strength indicator (ldr-strength-weak)');
            testsPassed++;
        } else {
            console.log(`❌ Expected ldr-strength-weak class, got: "${strengthClasses}"`);
            testsFailed++;
        }

        // Test strong password
        await page.evaluate(() => document.querySelector('input[name="password"]').value = '');
        await page.type('input[name="password"]', 'StrongPass123!', { delay: 50 });
        await new Promise(resolve => setTimeout(resolve, 200));

        strengthClasses = await page.evaluate(el => el.className, strengthBar);
        console.log(`   Strong password "StrongPass123!" - classes: "${strengthClasses}"`);

        if (strengthClasses.includes('ldr-strength-strong')) {
            console.log('✅ Strong password shows strong strength indicator (ldr-strength-strong)');
            testsPassed++;
        } else {
            console.log(`❌ Expected ldr-strength-strong class, got: "${strengthClasses}"`);
            testsFailed++;
        }

        // Test 4: Password mismatch detection
        console.log('\n📋 Test 4: Password mismatch detection');

        // Set up form with mismatched passwords
        await page.evaluate(() => {
            document.querySelector('input[name="username"]').value = '';
            document.querySelector('input[name="password"]').value = '';
            document.querySelector('input[name="confirm_password"]').value = '';
        });

        const testUsername = `flowtest_${Date.now()}`;
        await page.type('input[name="username"]', testUsername, { delay: 30 });
        await page.type('input[name="password"]', 'Password123!', { delay: 30 });
        await page.type('input[name="confirm_password"]', 'DifferentPass!', { delay: 30 });

        // Check the acknowledgment checkbox
        const acknowledgeCheckbox = await page.$('input[name="acknowledge"]');
        const isChecked = await page.evaluate(el => el.checked, acknowledgeCheckbox);
        if (!isChecked) {
            await page.click('input[name="acknowledge"]');
        }

        // Set up dialog handler to catch the alert
        let alertMessage = null;
        page.once('dialog', async dialog => {
            alertMessage = dialog.message();
            await dialog.accept();
        });

        // Try to submit the form
        await page.click('button[type="submit"]');
        await new Promise(resolve => setTimeout(resolve, 1000));

        if (alertMessage && alertMessage.includes('match')) {
            console.log(`✅ Password mismatch shows alert: "${alertMessage}"`);
            testsPassed++;
        } else {
            console.log('❌ Password mismatch should show alert about non-matching passwords');
            testsFailed++;
        }

        // Test 5: Acknowledgment checkbox required
        console.log('\n📋 Test 5: Acknowledgment checkbox validation');

        // Reload the page to reset form
        await page.goto(`${baseUrl}/auth/register`, {
            waitUntil: 'domcontentloaded',
            timeout: 30000
        });

        // Fill form correctly but don't check acknowledgment
        await page.type('input[name="username"]', `acktest_${Date.now()}`, { delay: 30 });
        await page.type('input[name="password"]', 'ValidPass123!', { delay: 30 });
        await page.type('input[name="confirm_password"]', 'ValidPass123!', { delay: 30 });

        // Don't check the checkbox - verify it's required
        const checkbox = await page.$('input[name="acknowledge"]');
        const checkboxValidity = await page.evaluate(el => ({
            valid: el.validity.valid,
            valueMissing: el.validity.valueMissing,
            required: el.required
        }), checkbox);

        console.log(`   Checkbox required: ${checkboxValidity.required}, valueMissing: ${checkboxValidity.valueMissing}`);

        if (checkboxValidity.required) {
            console.log('✅ Acknowledgment checkbox is required');
            testsPassed++;
        } else {
            console.log('❌ Acknowledgment checkbox should be required');
            testsFailed++;
        }

        // Test 6: Full successful registration flow
        // Uses AuthHelper for robust CI-compatible registration with proper timeouts
        console.log('\n📋 Test 6: Full successful registration flow');

        // Create a fresh page to ensure clean state
        const freshPage = await browser.newPage();

        // Set timeouts for the fresh page
        if (isCI) {
            freshPage.setDefaultTimeout(120000);  // 2 minutes
            freshPage.setDefaultNavigationTimeout(120000);  // 2 minutes
        }

        try {
            const newUsername = `fullflow_${Date.now()}`;
            const newPassword = 'SecurePass123!';
            console.log(`   Registering user: ${newUsername}`);

            // Use AuthHelper which has robust CI-compatible registration logic
            const freshAuthHelper = new AuthHelper(freshPage, baseUrl);
            await freshAuthHelper.register(newUsername, newPassword);

            console.log('✅ Successful registration completed');
            testsPassed++;

            // Test 7: Newly registered user can access protected pages
            console.log('\n📋 Test 7: Newly registered user can access system');

            // Verify we're logged in by checking if we can access settings
            const isLoggedIn = await freshAuthHelper.isLoggedIn();
            if (isLoggedIn) {
                try {
                    await freshPage.goto(`${baseUrl}/settings/`, {
                        waitUntil: 'domcontentloaded',
                        timeout: 60000
                    });

                    const settingsUrl = freshPage.url();
                    if (settingsUrl.includes('/settings')) {
                        console.log('✅ Newly registered user can access protected pages');
                        testsPassed++;
                    } else {
                        console.log(`❌ User redirected to: ${settingsUrl}`);
                        testsFailed++;
                    }
                } catch (settingsError) {
                    console.log(`⚠️  Could not load settings page: ${settingsError.message}`);
                    testsFailed++;
                }
            } else {
                console.log('❌ User not logged in after registration');
                testsFailed++;
            }
        } catch (regError) {
            console.log(`❌ Registration failed: ${regError.message}`);
            testsFailed++;
            // Also fail Test 7 since it depends on Test 6
            console.log('\n📋 Test 7: Newly registered user can access system');
            console.log('⏭️  SKIPPED - depends on Test 6 which failed');
            testsFailed++;
        } finally {
            await freshPage.close();
        }

        // Take a screenshot of the final state (skipped in CI)
        await takeScreenshot(page, path.join(screenshotsDir, 'register_full_flow_test.png'), { fullPage: true });

        // Summary
        console.log('\n' + '='.repeat(50));
        console.log(`📊 Test Summary: ${testsPassed} passed, ${testsFailed} failed`);
        console.log('='.repeat(50));

        if (testsFailed > 0) {
            throw new Error(`${testsFailed} test(s) failed`);
        }

        console.log('\n🎉 All registration full flow tests passed!');

    } catch (error) {
        console.error('\n❌ Test failed:', error.message);

        // Take error screenshot (skipped in CI)
        await takeScreenshot(page, path.join(screenshotsDir, 'register_full_flow_error.png'), { fullPage: true });

        await browser.close();
        process.exit(1);
    }

    await browser.close();
    console.log('\n✅ Test completed successfully');
}

// Run the test
testRegisterFullFlow().catch(console.error);
