/**
 * Collections Auto-Index Toggle UI Test
 *
 * Tests the auto-index toggle on the collections page that controls
 * whether documents are automatically indexed when uploaded or downloaded.
 *
 * What this tests:
 * - Toggle loads initial state from settings API
 * - Toggle changes persist to settings API
 * - Toggle reflects correct state after page reload
 * - Error handling when API calls fail
 *
 * Prerequisites: Web server running on http://127.0.0.1:5000
 *
 * Usage: node tests/ui_tests/test_collections_auto_index.js
 */

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

const BASE_URL = 'http://127.0.0.1:5000';
const COLLECTIONS_URL = `${BASE_URL}/library/collections`;
const SETTINGS_API_KEY = 'research_library.auto_index_enabled';

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

async function runTests() {
    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());
    const page = await browser.newPage();
    const authHelper = new AuthHelper(page, BASE_URL);

    let passed = 0;
    let failed = 0;

    // Monitor console errors
    const consoleErrors = [];
    page.on('console', msg => {
        if (msg.type() === 'error') {
            consoleErrors.push(msg.text());
            console.log('  Browser console error:', msg.text());
        }
    });

    // Monitor network errors
    const networkErrors = [];
    page.on('response', response => {
        if (response.status() >= 400) {
            networkErrors.push({ status: response.status(), url: response.url() });
        }
    });

    try {
        console.log('🧪 Testing Collections Auto-Index Toggle\n');

        // Authenticate first
        console.log('📝 Authenticating...');
        await authHelper.ensureAuthenticated();
        console.log('✅ Authenticated\n');

        // Test 1: Toggle exists on collections page
        console.log('Test 1: Toggle exists on collections page');
        await page.goto(COLLECTIONS_URL, { waitUntil: 'domcontentloaded', timeout: 30000 });
        await delay(2000); // Wait for JS to load and execute

        const toggleExists = await page.$('#auto-index-toggle');
        if (toggleExists) {
            console.log('  ✅ Toggle element found');
            passed++;
        } else {
            console.log('  ❌ Toggle element not found');
            failed++;
        }

        // Test 2: Toggle has associated label with tooltip
        console.log('\nTest 2: Toggle has label with tooltip');
        const labelExists = await page.$('label.ldr-checkbox-label');
        const hasTooltip = await page.evaluate(() => {
            const span = document.querySelector('label.ldr-checkbox-label .ldr-tooltip');
            return span !== null;
        });

        if (labelExists && hasTooltip) {
            console.log('  ✅ Label with tooltip exists');
            passed++;
        } else {
            console.log(`  ❌ Label (${!!labelExists}) or tooltip (${hasTooltip}) missing`);
            failed++;
        }

        // Test 3: Toggle loads initial state from API
        console.log('\nTest 3: Toggle loads state from settings API');

        // Get the current setting value directly from API
        const apiResponse = await page.evaluate(async (key) => {
            const response = await fetch(`/settings/api/${key}`);
            return response.json();
        }, SETTINGS_API_KEY);

        const toggleChecked = await page.evaluate(() => {
            return document.getElementById('auto-index-toggle').checked;
        });

        const expectedChecked = apiResponse.value === true || apiResponse.value === 'true';
        if (toggleChecked === expectedChecked) {
            console.log(`  ✅ Toggle state (${toggleChecked}) matches API value (${apiResponse.value})`);
            passed++;
        } else {
            console.log(`  ❌ Toggle state (${toggleChecked}) does not match API value (${apiResponse.value})`);
            failed++;
        }

        // Test 4: Toggle change persists to API
        console.log('\nTest 4: Toggle change persists to API');
        const initialState = toggleChecked;

        // Click the toggle to change state
        await page.click('#auto-index-toggle');
        await delay(1000); // Wait for API call

        // Verify state changed in UI
        const newToggleState = await page.evaluate(() => {
            return document.getElementById('auto-index-toggle').checked;
        });

        // Verify state changed in API
        const newApiResponse = await page.evaluate(async (key) => {
            const response = await fetch(`/settings/api/${key}`);
            return response.json();
        }, SETTINGS_API_KEY);

        const expectedNewState = newApiResponse.value === true || newApiResponse.value === 'true';

        if (newToggleState !== initialState && newToggleState === expectedNewState) {
            console.log(`  ✅ Toggle changed from ${initialState} to ${newToggleState} and API reflects this`);
            passed++;
        } else {
            console.log(`  ❌ Toggle change failed: UI=${newToggleState}, API=${newApiResponse.value}, expected different from ${initialState}`);
            failed++;
        }

        // Test 5: State persists after page reload
        console.log('\nTest 5: State persists after page reload');
        const stateBeforeReload = newToggleState;

        await page.reload({ waitUntil: 'domcontentloaded', timeout: 30000 });
        await delay(2000); // Wait for JS to load state

        const stateAfterReload = await page.evaluate(() => {
            return document.getElementById('auto-index-toggle').checked;
        });

        if (stateAfterReload === stateBeforeReload) {
            console.log(`  ✅ State persisted after reload: ${stateAfterReload}`);
            passed++;
        } else {
            console.log(`  ❌ State changed after reload: was ${stateBeforeReload}, now ${stateAfterReload}`);
            failed++;
        }

        // Test 6: Toggle back to original state
        console.log('\nTest 6: Toggle back to original state');
        await page.click('#auto-index-toggle');
        await delay(1000);

        const restoredState = await page.evaluate(() => {
            return document.getElementById('auto-index-toggle').checked;
        });

        if (restoredState === initialState) {
            console.log(`  ✅ Restored to original state: ${restoredState}`);
            passed++;
        } else {
            console.log(`  ❌ Failed to restore: expected ${initialState}, got ${restoredState}`);
            failed++;
        }

        // Test 7: No console or network errors during tests
        console.log('\nTest 7: No critical errors during tests');
        const criticalConsoleErrors = consoleErrors.filter(e =>
            !e.includes('favicon') && !e.includes('404')
        );
        const criticalNetworkErrors = networkErrors.filter(e =>
            !e.url.includes('favicon') && e.status >= 500
        );

        if (criticalConsoleErrors.length === 0 && criticalNetworkErrors.length === 0) {
            console.log('  ✅ No critical errors');
            passed++;
        } else {
            console.log(`  ❌ Found errors: ${criticalConsoleErrors.length} console, ${criticalNetworkErrors.length} network`);
            criticalConsoleErrors.forEach(e => console.log(`    Console: ${e}`));
            criticalNetworkErrors.forEach(e => console.log(`    Network: ${e.status} ${e.url}`));
            failed++;
        }

        // Take screenshot for debugging
        await takeScreenshot(page, '/tmp/collections_auto_index_test.png');

    } catch (error) {
        console.error('\n❌ Test error:', error.message);
        await takeScreenshot(page, '/tmp/collections_auto_index_error.png');
        failed++;
    } finally {
        await browser.close();
    }

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

    process.exit(failed > 0 ? 1 : 0);
}

runTests();
