/**
 * Puppeteer test for OpenAI API key configuration through the UI.
 *
 * This test verifies:
 * 1. User can navigate to settings
 * 2. User can enter OpenAI API key
 * 3. Settings are saved correctly
 * 4. API key is used for research
 */

const puppeteer = require('puppeteer');
const { expect } = require('chai');

// Test configuration
const BASE_URL = process.env.TEST_URL || 'http://localhost:5000';
const TEST_USERNAME = 'test_openai_user';
const TEST_PASSWORD = 'Test_password_123';
const TEST_OPENAI_KEY = 'sk-test-1234567890abcdef';

describe('OpenAI API Key Configuration UI Test', function() {
    this.timeout(60000); // 60 second timeout for UI tests

    let browser;
    let page;

    before(async () => {
        browser = await puppeteer.launch({
            headless: process.env.HEADLESS !== 'false',
            args: ['--no-sandbox', '--disable-setuid-sandbox']
        });
        page = await browser.newPage();

        // Set viewport for consistent testing
        await page.setViewport({ width: 1280, height: 720 });

        // Enable console logging for debugging
        page.on('console', msg => console.log('Browser console:', msg.text()));
    });

    after(async () => {
        if (browser) {
            await browser.close();
        }
    });

    beforeEach(async () => {
        // Navigate to home page before each test
        await page.goto(BASE_URL, { waitUntil: 'domcontentloaded' });
    });

    describe('User Registration and Login', () => {
        it('should register a new user', async () => {
            // Click on Register link
            await page.waitForSelector('a[href="/register"]');
            await page.click('a[href="/register"]');

            // Wait for registration form
            await page.waitForSelector('form#registerForm');

            // Fill registration form
            await page.type('input[name="username"]', TEST_USERNAME);
            await page.type('input[name="password"]', TEST_PASSWORD);
            await page.type('input[name="confirm_password"]', TEST_PASSWORD);

            // Submit form
            await page.click('button[type="submit"]');

            // Wait for redirect to login or dashboard
            await page.waitForNavigation({ waitUntil: 'domcontentloaded' });

            // Check if registration was successful
            const url = page.url();
            expect(url).to.include('/login').or.to.include('/');
        });

        it('should login with credentials', async () => {
            // Navigate to login if not already there
            const currentUrl = page.url();
            if (!currentUrl.includes('/login')) {
                await page.goto(`${BASE_URL}/login`, { waitUntil: 'domcontentloaded' });
            }

            // Wait for login form
            await page.waitForSelector('form');

            // Fill login form
            await page.type('input[name="username"]', TEST_USERNAME);
            await page.type('input[name="password"]', TEST_PASSWORD);

            // Submit form
            await page.click('button[type="submit"]');

            // Wait for redirect to dashboard
            await page.waitForNavigation({ waitUntil: 'domcontentloaded' });

            // Verify we're logged in
            const dashboardElement = await page.$('.dashboard, #dashboard, [data-page="home"]');
            expect(dashboardElement).to.not.be.null;
        });
    });

    describe('OpenAI API Key Configuration', () => {
        beforeEach(async () => {
            // Ensure we're logged in
            await loginUser(page, TEST_USERNAME, TEST_PASSWORD);
        });

        it('should navigate to settings page', async () => {
            // Click on Settings link/button
            const settingsSelector = 'a[href="/settings"], button:contains("Settings"), .settings-link';
            await page.waitForSelector(settingsSelector);
            await page.click(settingsSelector);

            // Wait for settings page to load
            await page.waitForSelector('.settings-page, #settings, [data-page="settings"]');

            // Verify we're on settings page
            const url = page.url();
            expect(url).to.include('/settings');
        });

        it('should configure OpenAI provider and API key', async () => {
            // Navigate to settings
            await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });

            // Select OpenAI as provider
            const providerSelect = await page.$('select[name="llm.provider"], #llm-provider');
            if (providerSelect) {
                await page.select('select[name="llm.provider"], #llm-provider', 'openai');
            } else {
                // Alternative: click on OpenAI option if using custom dropdown
                await page.click('[data-provider="openai"], .provider-option[data-value="openai"]');
            }

            // Wait for OpenAI settings to appear
            await page.waitForSelector('input[name="llm.openai.api_key"], #openai-api-key', { visible: true });

            // Clear and enter API key
            const apiKeyInput = await page.$('input[name="llm.openai.api_key"], #openai-api-key');
            await apiKeyInput.click({ clickCount: 3 }); // Select all
            await apiKeyInput.type(TEST_OPENAI_KEY);

            // Select model (optional)
            const modelSelect = await page.$('select[name="llm.model"], #llm-model');
            if (modelSelect) {
                await page.select('select[name="llm.model"], #llm-model', 'gpt-3.5-turbo');
            }

            // Save settings
            await page.click('button[type="submit"], .save-settings, #save-settings');

            // Wait for save confirmation
            await page.waitForSelector('.success-message, .toast-success, [data-status="success"]', {
                timeout: 5000
            });

            // Verify settings were saved
            const successMessage = await page.$eval(
                '.success-message, .toast-success, [data-status="success"]',
                el => el.textContent
            );
            expect(successMessage).to.include('saved').or.to.include('success');
        });

        it('should mask API key after saving', async () => {
            // Navigate to settings
            await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });

            // Wait for settings to load
            await page.waitForSelector('input[name="llm.openai.api_key"], #openai-api-key');

            // Check if API key is masked
            const apiKeyInput = await page.$('input[name="llm.openai.api_key"], #openai-api-key');
            const inputType = await apiKeyInput.evaluate(el => el.type);
            const inputValue = await apiKeyInput.evaluate(el => el.value);

            // Should be password type or show masked value
            expect(inputType).to.equal('password').or.expect(inputValue).to.match(/\*{4,}/);
        });
    });

    describe('Research with OpenAI', () => {
        beforeEach(async () => {
            // Ensure we're logged in and have OpenAI configured
            await loginUser(page, TEST_USERNAME, TEST_PASSWORD);
        });

        it('should perform research using configured OpenAI API', async () => {
            // Navigate to home/research page
            await page.goto(BASE_URL, { waitUntil: 'domcontentloaded' });

            // Find and fill research query input
            await page.waitForSelector('input[name="query"], #query, .search-input');
            await page.type('input[name="query"], #query, .search-input', 'What is machine learning?');

            // Click search/research button
            await page.click('button[type="submit"], .search-button, #start-research');

            // Wait for research to start
            await page.waitForSelector('.research-status, .loading, [data-status="running"]', {
                timeout: 10000
            });

            // Wait for research to complete (with longer timeout)
            await page.waitForSelector('.research-complete, .research-summary, [data-status="completed"]', {
                timeout: 30000
            });

            // Verify results contain expected content
            const summaryText = await page.$eval(
                '.research-summary, .summary-content, [data-content="summary"]',
                el => el.textContent
            );

            expect(summaryText).to.include('machine learning').or.to.include('Machine Learning');
            expect(summaryText.length).to.be.greaterThan(100); // Should have substantial content
        });

        it('should show error if API key is invalid', async () => {
            // Configure with invalid API key
            await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });

            // Set invalid API key
            const apiKeyInput = await page.$('input[name="llm.openai.api_key"], #openai-api-key');
            await apiKeyInput.click({ clickCount: 3 });
            await apiKeyInput.type('sk-invalid-key');

            // Save settings
            await page.click('button[type="submit"], .save-settings, #save-settings');
            await page.waitForTimeout(1000); // Wait for save

            // Try to perform research
            await page.goto(BASE_URL, { waitUntil: 'domcontentloaded' });
            await page.type('input[name="query"], #query, .search-input', 'Test query');
            await page.click('button[type="submit"], .search-button, #start-research');

            // Wait for error message
            await page.waitForSelector('.error-message, .toast-error, [data-status="error"]', {
                timeout: 15000
            });

            // Verify error message mentions API key or authentication
            const errorText = await page.$eval(
                '.error-message, .toast-error, [data-status="error"]',
                el => el.textContent
            );

            expect(errorText.toLowerCase()).to.include('api').or.include('auth').or.include('key');
        });
    });

    describe('Settings Persistence', () => {
        it('should persist OpenAI settings across sessions', async () => {
            // Login
            await loginUser(page, TEST_USERNAME, TEST_PASSWORD);

            // Configure OpenAI
            await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });
            await page.select('select[name="llm.provider"], #llm-provider', 'openai');
            await page.type('input[name="llm.openai.api_key"], #openai-api-key', TEST_OPENAI_KEY);
            await page.click('button[type="submit"], .save-settings, #save-settings');

            // Wait for save
            await page.waitForTimeout(2000);

            // Logout
            await page.click('a[href="/logout"], .logout-button, #logout');
            await page.waitForNavigation({ waitUntil: 'domcontentloaded' });

            // Login again
            await loginUser(page, TEST_USERNAME, TEST_PASSWORD);

            // Go to settings
            await page.goto(`${BASE_URL}/settings`, { waitUntil: 'domcontentloaded' });

            // Verify provider is still OpenAI
            const selectedProvider = await page.$eval(
                'select[name="llm.provider"], #llm-provider',
                el => el.value
            );
            expect(selectedProvider).to.equal('openai');

            // Verify API key field has value (even if masked)
            const apiKeyValue = await page.$eval(
                'input[name="llm.openai.api_key"], #openai-api-key',
                el => el.value
            );
            expect(apiKeyValue).to.not.be.empty;
        });
    });
});

// Helper function to login
async function loginUser(page, username, password) {
    const currentUrl = page.url();

    // Check if already logged in
    if (currentUrl.includes('/settings') || currentUrl.includes('/research')) {
        return;
    }

    // Navigate to login
    await page.goto(`${BASE_URL}/login`, { waitUntil: 'domcontentloaded' });

    // Fill and submit login form
    await page.type('input[name="username"]', username);
    await page.type('input[name="password"]', password);
    await page.click('button[type="submit"]');

    // Wait for redirect
    await page.waitForNavigation({ waitUntil: 'domcontentloaded' });
}
