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

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

function log(message, type = 'info') {
    const timestamp = new Date().toISOString();
    const prefix = {
        info: `${colors.blue}ℹ`,
        success: `${colors.green}✓`,
        error: `${colors.red}ERROR:`,
        warn: `${colors.yellow}⚠`
    }[type] || '';

    console.log(`${prefix}[${timestamp}] ${message}${colors.reset}`);
}

(async () => {
    let browser;
    let authHelper;

    try {
        // Test configuration
        const TEST_API_KEY_1 = 'test-api-key-12345';
        const TEST_API_KEY_2 = 'changed-api-key-67890';
        const BASE_URL = 'http://localhost:5000';

        log(`${colors.bright}=== Starting API Key Settings Test ===${colors.reset}`, 'info');

        // Launch browser
    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());

        log('Browser launched', 'success');

        const page = await browser.newPage();
        await page.setViewport({ width: 1920, height: 1080 });

        // Set up console logging
        page.on('console', msg => {
            const text = msg.text();
            if (text.includes('ERROR') || text.includes('Failed')) {
                log(`Browser console: ${text}`, 'error');
            } else {
                log(`Browser console: ${text}`, 'info');
            }
        });

        // Initialize auth helper
        authHelper = new AuthHelper(page);

        // Create test user with timestamp
        const timestamp = Date.now();
        const testUsername = `api_test_${timestamp}`;
        const testPassword = 'testpass123';

        log(`Creating user: ${testUsername}`, 'info');

        // Register and login
        await authHelper.register(testUsername, testPassword);
        const isAuthenticated = await authHelper.isLoggedIn();
        if (!isAuthenticated) {
            throw new Error('Failed to authenticate after registration');
        }
        log('User authenticated successfully', 'success');

        // Navigate to settings page
        log('Navigating to settings page...', 'info');
        await page.goto(`${BASE_URL}/settings`, { waitUntil: 'networkidle2' });

        // Check if we got redirected to login
        const currentUrl = page.url();
        if (currentUrl.includes('/auth/login')) {
            log('Redirected to login page, attempting to login again...', 'warn');
            // Try to login again
            await authHelper.login(testUsername, testPassword);
            // Navigate to settings again
            await page.goto(`${BASE_URL}/settings`, { waitUntil: 'networkidle2' });
        }

        // Wait for settings to load - try multiple selectors
        try {
            await page.waitForSelector('.settings-container, #settings-content, .settings-page, main', { timeout: 5000 });
        } catch (e) {
            log('Settings container not found, continuing anyway...', 'warn');
        }

        // Take screenshot of initial settings page
        await page.screenshot({
            path: `/tmp/api_key_test_settings_initial_${timestamp}.png`,
            fullPage: true
        });
        log('Screenshot saved: Initial settings page', 'info');

        // Debug: Check page title and URL
        const pageTitle = await page.title();
        const pageUrl = page.url();
        log(`Current page - Title: ${pageTitle}, URL: ${pageUrl}`, 'info');

        // Find and click on LLM settings section
        log('Looking for LLM settings section...', 'info');

        // Click on LLM section in the sidebar if needed - use simpler selectors
        const llmSectionSelectors = ['a[href="#llm"]', '.nav-link:contains("LLM")', 'button:contains("LLM")'];
        let clicked = false;
        for (const selector of llmSectionSelectors) {
            try {
                if (await page.$(selector)) {
                    await page.click(selector);
                    await new Promise(resolve => setTimeout(resolve, 500));
                    log(`Clicked LLM section with selector: ${selector}`, 'success');
                    clicked = true;
                    break;
                }
            } catch (e) {
                // Try next selector
            }
        }

        // Look for OpenAI Endpoint subsection
        const openaiEndpointSelectors = ['a[href="#llm-openai-endpoint"]', '.nav-link:contains("OpenAI Endpoint")', 'button:contains("OpenAI Endpoint")'];
        for (const selector of openaiEndpointSelectors) {
            try {
                if (await page.$(selector)) {
                    await page.click(selector);
                    await new Promise(resolve => setTimeout(resolve, 500));
                    log(`Clicked OpenAI Endpoint section with selector: ${selector}`, 'success');
                    break;
                }
            } catch (e) {
                // Try next selector
            }
        }

        // Find the API key input field
        log('Looking for OpenAI Endpoint API key field...', 'info');

        // Try multiple selectors for the API key field
        const apiKeySelectors = [
            'input[name="llm.openai_endpoint.api_key"]',
            'input[id="llm.openai_endpoint.api_key"]',
            'input[data-setting="llm.openai_endpoint.api_key"]',
            'input[type="password"][name*="openai_endpoint"]',
            'input[type="text"][name*="openai_endpoint.api_key"]'
        ];

        let apiKeyInput = null;
        for (const selector of apiKeySelectors) {
            apiKeyInput = await page.$(selector);
            if (apiKeyInput) {
                log(`Found API key input with selector: ${selector}`, 'success');
                break;
            }
        }

        if (!apiKeyInput) {
            // Try to find it by label
            const labels = await page.$$('label');
            for (const label of labels) {
                const text = await label.evaluate(el => el.textContent);
                if (text.toLowerCase().includes('openai endpoint') && text.toLowerCase().includes('api key')) {
                    const forAttr = await label.evaluate(el => el.getAttribute('for'));
                    if (forAttr) {
                        apiKeyInput = await page.$(`#${forAttr}`);
                        if (apiKeyInput) {
                            log(`Found API key input via label: ${forAttr}`, 'success');
                            break;
                        }
                    }
                }
            }
        }

        if (!apiKeyInput) {
            throw new Error('Could not find OpenAI Endpoint API key input field');
        }

        // Clear and set first API key
        log(`Setting API key to: ${TEST_API_KEY_1}`, 'info');
        await apiKeyInput.click({ clickCount: 3 });
        await apiKeyInput.type(TEST_API_KEY_1);

        // Find and click save button
        log('Looking for save button...', 'info');
        const saveButtonSelectors = [
            'button[type="submit"]',
            'button:has-text("Save")',
            'button.btn-primary:has-text("Save")',
            '.save-btn',
            'button.save-settings'
        ];

        let saveButton = null;
        for (const selector of saveButtonSelectors) {
            try {
                saveButton = await page.waitForSelector(selector, { timeout: 2000 });
                if (saveButton) {
                    log(`Found save button with selector: ${selector}`, 'success');
                    break;
                }
            } catch (e) {
                // Continue to next selector
            }
        }

        if (saveButton) {
            await saveButton.click();
            log('Clicked save button', 'success');

            // Wait for save confirmation
            await new Promise(resolve => setTimeout(resolve, 2000));

            // Take screenshot after first save
            await page.screenshot({
                path: `/tmp/api_key_test_after_first_save_${timestamp}.png`,
                fullPage: true
            });
            log('Screenshot saved: After first API key save', 'info');
        }

        // Refresh page to verify persistence
        log('Refreshing page to verify API key persistence...', 'info');
        await page.reload({ waitUntil: 'networkidle2' });
        await new Promise(resolve => setTimeout(resolve, 1000));

        // Navigate back to OpenAI Endpoint settings
        for (const selector of llmSectionSelectors) {
            try {
                if (await page.$(selector)) {
                    await page.click(selector);
                    await new Promise(resolve => setTimeout(resolve, 500));
                    break;
                }
            } catch (e) {
                // Try next selector
            }
        }

        for (const selector of openaiEndpointSelectors) {
            try {
                if (await page.$(selector)) {
                    await page.click(selector);
                    await new Promise(resolve => setTimeout(resolve, 500));
                    break;
                }
            } catch (e) {
                // Try next selector
            }
        }

        // Find API key input again
        apiKeyInput = null;
        for (const selector of apiKeySelectors) {
            apiKeyInput = await page.$(selector);
            if (apiKeyInput) break;
        }

        if (apiKeyInput) {
            // Get current value
            const currentValue = await apiKeyInput.evaluate(el => el.value);
            log(`Current API key value after refresh: ${currentValue ? '***' + currentValue.slice(-5) : 'empty'}`, 'info');

            if (currentValue && currentValue.includes(TEST_API_KEY_1.slice(-5))) {
                log('API key persisted correctly after refresh!', 'success');
            } else {
                log('API key did not persist after refresh', 'error');
            }

            // Now change to second API key
            log(`Changing API key to: ${TEST_API_KEY_2}`, 'info');
            await apiKeyInput.click({ clickCount: 3 });
            await apiKeyInput.type(TEST_API_KEY_2);

            // Save again
            if (saveButton) {
                await saveButton.click();
                log('Clicked save button for second API key', 'success');
                await new Promise(resolve => setTimeout(resolve, 2000));
            }
        }

        // Make an API call to verify the setting was saved
        log('Verifying API key via API call...', 'info');
        const apiResponse = await page.evaluate(async () => {
            try {
                const response = await fetch('/api/settings', {
                    credentials: 'same-origin'
                });
                const data = await response.json();

                // Look for the API key setting
                const apiKeySetting = data.settings?.find(s =>
                    s.key === 'llm.openai_endpoint.api_key' ||
                    s.setting_key === 'llm.openai_endpoint.api_key'
                );

                return {
                    success: response.ok,
                    apiKeyFound: !!apiKeySetting,
                    apiKeyValue: apiKeySetting?.value,
                    allSettings: data.settings?.map(s => s.key || s.setting_key)
                };
            } catch (error) {
                return { success: false, error: error.message };
            }
        });

        if (apiResponse.success) {
            log(`API call successful. API key found: ${apiResponse.apiKeyFound}`, 'info');
            if (apiResponse.apiKeyValue) {
                log(`API key value from API: ***${apiResponse.apiKeyValue.slice(-5)}`, 'info');
            }
            if (apiResponse.allSettings) {
                log(`Total settings found: ${apiResponse.allSettings.length}`, 'info');
                const llmSettings = apiResponse.allSettings.filter(s => s && s.startsWith('llm.'));
                log(`LLM settings found: ${llmSettings.length}`, 'info');
            }
        } else {
            log(`API call failed: ${apiResponse.error}`, 'error');
        }

        // Take final screenshot
        await page.screenshot({
            path: `/tmp/api_key_test_final_${timestamp}.png`,
            fullPage: true
        });
        log('Screenshot saved: Final state', 'info');

        // Try to trigger a research to see if the API key is being used
        log('Testing if API key is accessible for research...', 'info');
        await page.goto(`${BASE_URL}/`, { waitUntil: 'networkidle2' });

        // Get final status
        const finalUrl = page.url();
        log(`Final page URL: ${finalUrl}`, 'info');

        log('API Key Settings test completed', 'success');

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

        // Take error screenshot
        if (browser) {
            const page = (await browser.pages())[0];
            if (page) {
                await page.screenshot({
                    path: `/tmp/api_key_test_error_${Date.now()}.png`,
                    fullPage: true
                });
                log('Error screenshot saved', 'info');
            }
        }

        process.exit(1);
    } finally {
        if (browser) {
            await browser.close();
            log('Browser closed', 'success');
        }
    }
})();
