const puppeteer = require('puppeteer');
const path = require('path');
const { getPuppeteerLaunchOptions } = require('./puppeteer_config');

// Test configuration
const BASE_URL = 'http://127.0.0.1:5000';
const TEST_USER = `settings_persist_${Date.now()}`;
const TEST_PASSWORD = 'TestPass123!';

// Colors for console output
const colors = {
    reset: '\x1b[0m',
    bright: '\x1b[1m',
    green: '\x1b[32m',
    red: '\x1b[31m',
    yellow: '\x1b[33m',
    blue: '\x1b[34m',
    cyan: '\x1b[36m'
};

function log(message, type = 'info') {
    const timestamp = new Date().toISOString().split('T')[1].split('.')[0];
    const typeColors = {
        'info': colors.cyan,
        'success': colors.green,
        'error': colors.red,
        'warning': colors.yellow,
        'section': colors.blue
    };
    const color = typeColors[type] || colors.reset;
    console.log(`${color}[${timestamp}] ${message}${colors.reset}`);
}

async function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function registerUser(page) {
    log('📝 Registering new user...', 'info');

    await page.goto(`${BASE_URL}/register`);
    await page.waitForSelector('#username');

    await page.type('#username', TEST_USER);
    await page.type('#password', TEST_PASSWORD);
    await page.type('#password_confirm', TEST_PASSWORD);

    await page.click('button[type="submit"]');
    await page.waitForNavigation();

    log('✅ Registration successful', 'success');
}

async function loginUser(page) {
    log('🔐 Logging in...', 'info');

    await page.goto(`${BASE_URL}/login`);
    await page.waitForSelector('#username');

    await page.type('#username', TEST_USER);
    await page.type('#password', TEST_PASSWORD);

    await page.click('button[type="submit"]');
    await page.waitForNavigation();

    log('✅ Login successful', 'success');
}

async function modifySettings(page) {
    log('\n=== MODIFYING SETTINGS ===', 'section');

    await page.goto(`${BASE_URL}/settings`);
    await page.waitForSelector('.settings-form, #settings-form', { timeout: 10000 });

    const testSettings = {
        // LLM settings
        temperature: 0.8,
        maxTokens: 2048,
        contextWindow: 8192,

        // Search settings
        iterations: 2,
        questionsPerIteration: 3,
        maxResults: 15,
        timeRange: '1y',

        // Report settings
        citationFormat: 'domain_hyperlinks'
    };

    // Apply settings
    log('📝 Applying test settings...', 'info');

    // Temperature slider
    const tempSlider = await page.$('input[name="llm.temperature"], #temperature-slider');
    if (tempSlider) {
        await page.evaluate((value) => {
            const slider = document.querySelector('input[name="llm.temperature"], #temperature-slider');
            if (slider) {
                slider.value = value;
                slider.dispatchEvent(new Event('change', { bubbles: true }));
            }
        }, testSettings.temperature);
        log(`  - Temperature set to: ${testSettings.temperature}`, 'info');
    }

    // Max tokens
    const maxTokensInput = await page.$('input[name="llm.max_tokens"], #max-tokens');
    if (maxTokensInput) {
        await page.evaluate((el) => el.value = '', maxTokensInput);
        await page.type('input[name="llm.max_tokens"], #max-tokens', testSettings.maxTokens.toString());
        log(`  - Max tokens set to: ${testSettings.maxTokens}`, 'info');
    }

    // Search iterations
    const iterationsInput = await page.$('input[name="search.iterations"], #search-iterations');
    if (iterationsInput) {
        await page.evaluate((el) => el.value = '', iterationsInput);
        await page.type('input[name="search.iterations"], #search-iterations', testSettings.iterations.toString());
        log(`  - Search iterations set to: ${testSettings.iterations}`, 'info');
    }

    // Questions per iteration
    const questionsInput = await page.$('input[name="search.questions_per_iteration"], #questions-per-iteration');
    if (questionsInput) {
        await page.evaluate((el) => el.value = '', questionsInput);
        await page.type('input[name="search.questions_per_iteration"], #questions-per-iteration', testSettings.questionsPerIteration.toString());
        log(`  - Questions per iteration set to: ${testSettings.questionsPerIteration}`, 'info');
    }

    // Citation format dropdown
    const citationSelect = await page.$('select[name="report.citation_format"], #citation-format');
    if (citationSelect) {
        await page.select('select[name="report.citation_format"], #citation-format', testSettings.citationFormat);
        log(`  - Citation format set to: ${testSettings.citationFormat}`, 'info');
    }

    // Save settings
    log('💾 Saving settings...', 'info');
    const saveButton = await page.$('button[type="submit"], .save-settings-btn, #save-settings');
    if (saveButton) {
        await saveButton.click();
        await delay(2000); // Wait for save

        // Check for success message
        const successMessage = await page.$('.alert-success, .success-message');
        if (successMessage) {
            log('✅ Settings saved successfully', 'success');
        }
    }

    // Capture current settings
    const currentSettings = await page.evaluate(() => {
        const settings = {};

        // Get all input values
        const inputs = document.querySelectorAll('input[name], select[name], textarea[name]');
        inputs.forEach(input => {
            if (input.type === 'checkbox') {
                settings[input.name] = input.checked;
            } else {
                settings[input.name] = input.value;
            }
        });

        return settings;
    });

    return { testSettings, currentSettings };
}

async function verifySettingsPersistence(page, originalSettings) {
    log('\n=== VERIFYING SETTINGS PERSISTENCE ===', 'section');

    await page.goto(`${BASE_URL}/settings`);
    await page.waitForSelector('.settings-form, #settings-form', { timeout: 10000 });

    // Wait for settings to load
    await delay(2000);

    // Get current settings
    const persistedSettings = await page.evaluate(() => {
        const settings = {};

        // Temperature
        const tempSlider = document.querySelector('input[name="llm.temperature"], #temperature-slider');
        if (tempSlider) settings.temperature = parseFloat(tempSlider.value);

        // Max tokens
        const maxTokens = document.querySelector('input[name="llm.max_tokens"], #max-tokens');
        if (maxTokens) settings.maxTokens = parseInt(maxTokens.value);

        // Iterations
        const iterations = document.querySelector('input[name="search.iterations"], #search-iterations');
        if (iterations) settings.iterations = parseInt(iterations.value);

        // Questions per iteration
        const questions = document.querySelector('input[name="search.questions_per_iteration"], #questions-per-iteration');
        if (questions) settings.questionsPerIteration = parseInt(questions.value);

        // Citation format
        const citation = document.querySelector('select[name="report.citation_format"], #citation-format');
        if (citation) settings.citationFormat = citation.value;

        return settings;
    });

    // Compare settings
    log('🔍 Comparing settings...', 'info');
    let allMatch = true;

    Object.keys(originalSettings.testSettings).forEach(key => {
        const original = originalSettings.testSettings[key];
        const persisted = persistedSettings[key];

        if (original !== persisted) {
            log(`  ❌ ${key}: Expected ${original}, got ${persisted}`, 'error');
            allMatch = false;
        } else {
            log(`  ✅ ${key}: ${persisted} (matches)`, 'success');
        }
    });

    return allMatch;
}

async function testSettingsPersistence() {
    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());

    const page = await browser.newPage();

    // Set console log handler
    page.on('console', msg => {
        if (msg.type() === 'error' && !msg.text().includes('favicon')) {
            log(`Browser console error: ${msg.text()}`, 'error');
        }
    });

    try {
        // Step 1: Register and modify settings
        await registerUser(page);
        const settingsData = await modifySettings(page);

        // Step 2: Logout
        log('\n=== LOGGING OUT ===', 'section');
        await page.goto(`${BASE_URL}/logout`);
        await delay(1000);
        log('✅ Logged out', 'success');

        // Step 3: Login again
        await loginUser(page);

        // Step 4: Verify settings persisted
        const settingsMatch = await verifySettingsPersistence(page, settingsData);

        if (settingsMatch) {
            log('\n✅ All settings persisted correctly!', 'success');
        } else {
            throw new Error('Some settings did not persist correctly');
        }

        // Test settings on research page
        log('\n=== VERIFYING SETTINGS APPLY TO RESEARCH ===', 'section');
        await page.goto(`${BASE_URL}/research`);
        await page.waitForSelector('#research-form, .research-form');

        // Check if settings are reflected in research form
        const researchFormSettings = await page.evaluate(() => {
            const settings = {};

            // Check hidden inputs or data attributes
            const modelInput = document.querySelector('input[name="model"], #model');
            if (modelInput) settings.model = modelInput.value;

            const iterationsDisplay = document.querySelector('.iterations-display, [data-iterations]');
            if (iterationsDisplay) {
                settings.displayedIterations = iterationsDisplay.textContent ||
                                            iterationsDisplay.getAttribute('data-iterations');
            }

            return settings;
        });

        log('📊 Research form reflects settings', 'info');

        // Test settings reset
        log('\n=== TESTING SETTINGS RESET ===', 'section');
        await page.goto(`${BASE_URL}/settings`);

        const resetButton = await page.$('.reset-settings-btn, button[data-action="reset"]');
        if (resetButton) {
            await resetButton.click();

            // Handle confirmation dialog
            page.on('dialog', async dialog => {
                await dialog.accept();
            });

            await delay(2000);

            // Verify some settings returned to defaults
            const afterReset = await page.evaluate(() => {
                const temp = document.querySelector('input[name="llm.temperature"], #temperature-slider');
                return temp ? parseFloat(temp.value) : null;
            });

            if (afterReset !== null && afterReset !== settingsData.testSettings.temperature) {
                log('✅ Reset functionality works', 'success');
            }
        }

        // Capture final screenshot
        await page.screenshot({
            path: path.join(__dirname, 'screenshots', 'settings_persistence_final.png'),
            fullPage: true
        });

        log('\n✅ Settings persistence test completed successfully!', 'success');

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

        // Capture error screenshot
        await page.screenshot({
            path: path.join(__dirname, 'screenshots', 'settings_persistence_error.png'),
            fullPage: true
        });

        throw error;
    } finally {
        await browser.close();
    }
}

// Run the test
testSettingsPersistence().catch(error => {
    console.error('Test execution failed:', error);
    process.exit(1);
});
