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

// Test configuration
const BASE_URL = 'http://127.0.0.1:5000';

// 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 startResearch(page, query) {
    log(`🔬 Starting research: "${query}"`, 'info');

    await page.goto(`${BASE_URL}/`, { waitUntil: 'networkidle2' });
    await page.waitForSelector('#query', { timeout: 10000 });

    // Use longer iterations for cancellation test
    await page.evaluate(() => {
        // Try to set iterations to a higher value if the field exists
        const iterationsInput = document.querySelector('input[name="iterations"], #iterations');
        if (iterationsInput) {
            iterationsInput.value = '3';
        }
    });

    // Set query
    await page.evaluate((q) => {
        document.getElementById('query').value = q;
    }, query);

    // Submit form and wait for potential navigation or AJAX response
    const submitButton = await page.$('button[type="submit"], #submit-research, #start-research-btn');
    if (!submitButton) {
        log('❌ Submit button not found', 'error');
        return false;
    }

    // Click the submit button
    await submitButton.click();

    // Wait for page to settle after submission
    await delay(3000);

    // Verify research started - use try-catch in case of navigation context issues
    try {
        const progressStarted = await page.evaluate(() => {
            const progressBar = document.querySelector('.progress-bar, [role="progressbar"]');
            const progressText = document.querySelector('.progress-info, .progress-text');
            return progressBar || progressText;
        });

        if (progressStarted) {
            log('✅ Research started successfully', 'success');
            return true;
        }
    } catch (e) {
        // If execution context was destroyed, the page likely navigated to progress page
        // which means research started successfully
        if (e.message.includes('Execution context was destroyed')) {
            log('✅ Research started (page navigated)', 'success');
            return true;
        }
        throw e;
    }

    return false;
}

async function testCancellation() {
    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 {
        // Register user using AuthHelper for consistent behavior
        const auth = new AuthHelper(page, BASE_URL);
        await auth.ensureAuthenticated();

        // Navigate to home page after authentication
        await page.goto(BASE_URL, { waitUntil: 'networkidle2', timeout: 10000 });

        // Test 1: Cancel during early stage
        log('\n=== TEST 1: EARLY CANCELLATION ===', 'section');

        await startResearch(page, 'Complex analysis of quantum computing applications');

        // Wait a bit then cancel
        await delay(3000);

        // Find and click cancel button
        const cancelButton = await page.$('.cancel-btn, .stop-btn, button[data-action="cancel"]');
        if (cancelButton) {
            log('🛑 Clicking cancel button...', 'info');

            // Handle potential confirmation dialog
            page.once('dialog', async dialog => {
                log(`📋 Confirmation dialog: ${dialog.message()}`, 'info');
                await dialog.accept();
            });

            await cancelButton.click();
            await delay(2000);

            // Check if research was cancelled
            const cancelStatus = await page.evaluate(() => {
                const statusElement = document.querySelector('.status, .research-status');
                const progressText = document.querySelector('.progress-info, .progress-text');

                return {
                    status: statusElement?.textContent || '',
                    progress: progressText?.textContent || '',
                    hasCancelButton: !!document.querySelector('.cancel-btn, .stop-btn')
                };
            });

            log(`📊 Status after cancellation:`, 'info');
            log(`  - Status: ${cancelStatus.status}`, 'info');
            log(`  - Progress: ${cancelStatus.progress}`, 'info');

            if (cancelStatus.status.toLowerCase().includes('cancel') ||
                cancelStatus.status.toLowerCase().includes('stopped') ||
                cancelStatus.status.toLowerCase().includes('suspended')) {
                log('✅ Research cancelled successfully', 'success');
            }
        } else {
            log('⚠️ No cancel button found', 'warning');
        }

        // Test 2: Cancel during mid-stage
        log('\n=== TEST 2: MID-STAGE CANCELLATION ===', 'section');

        await startResearch(page, 'Comprehensive study of artificial intelligence ethics');

        // Wait for research to progress
        log('⏳ Waiting for research to progress...', 'info');
        await delay(10000); // Wait 10 seconds

        // Get progress before cancellation
        const progressBefore = await page.evaluate(() => {
            const progressBar = document.querySelector('.progress-bar, [role="progressbar"]');
            const progressText = document.querySelector('.progress-info, .progress-text');

            return {
                percentage: progressBar?.getAttribute('aria-valuenow') ||
                           progressBar?.style.width ||
                           progressText?.textContent || '0%',
                text: progressText?.textContent || ''
            };
        });

        log(`📊 Progress before cancellation: ${progressBefore.percentage}`, 'info');

        // Cancel research
        const cancelButton2 = await page.$('.cancel-btn, .stop-btn, button[data-action="cancel"]');
        if (cancelButton2) {
            page.once('dialog', async dialog => {
                await dialog.accept();
            });

            await cancelButton2.click();
            await delay(2000);

            const afterCancel = await page.evaluate(() => {
                const progressText = document.querySelector('.progress-info, .progress-text');
                const statusBadge = document.querySelector('.status-badge, .research-status');

                return {
                    progress: progressText?.textContent || '',
                    status: statusBadge?.textContent || ''
                };
            });

            log(`📊 After mid-stage cancellation:`, 'info');
            log(`  - Progress: ${afterCancel.progress}`, 'info');
            log(`  - Status: ${afterCancel.status}`, 'info');

            log('✅ Mid-stage cancellation tested', 'success');
        }

        // Test 3: Check cancelled research in history
        log('\n=== TEST 3: CANCELLED RESEARCH IN HISTORY ===', 'section');

        await page.goto(`${BASE_URL}/history`);
        await page.waitForSelector('.ldr-history-container, .ldr-history-list');

        const cancelledItems = await page.evaluate(() => {
            const items = [];
            const historyItems = document.querySelectorAll('.history-item');

            historyItems.forEach(item => {
                const status = item.querySelector('.status-badge, .status')?.textContent || '';
                const query = item.querySelector('.query-text, .research-query')?.textContent || '';

                if (status.toLowerCase().includes('cancel') ||
                    status.toLowerCase().includes('suspended') ||
                    status.toLowerCase().includes('stopped')) {
                    items.push({
                        query: query.trim(),
                        status: status.trim()
                    });
                }
            });

            return items;
        });

        if (cancelledItems.length > 0) {
            log(`✅ Found ${cancelledItems.length} cancelled research items in history:`, 'success');
            cancelledItems.forEach(item => {
                log(`  - "${item.query}" - Status: ${item.status}`, 'info');
            });
        } else {
            log('⚠️ No cancelled items found in history', 'warning');
        }

        // Test 4: Attempt to resume cancelled research (if feature exists)
        log('\n=== TEST 4: RESUME FUNCTIONALITY ===', 'section');

        const resumeButtons = await page.$$('.resume-btn, button[data-action="resume"]');
        if (resumeButtons.length > 0) {
            log('📊 Resume functionality available', 'info');

            // Click first resume button
            await resumeButtons[0].click();
            await delay(2000);

            // Check if research resumed
            const resumed = await page.evaluate(() => {
                return window.location.pathname.includes('/research') ||
                       window.location.pathname.includes('/progress');
            });

            if (resumed) {
                log('✅ Resume functionality works', 'success');
            }
        } else {
            log('ℹ️ No resume functionality found (might not be implemented)', 'info');
        }

        // Test 5: Multiple cancellations
        log('\n=== TEST 5: RAPID CANCELLATION ===', 'section');

        await startResearch(page, 'Quick test for immediate cancellation');

        // Cancel immediately
        await delay(500); // Very short delay

        const quickCancel = await page.$('.cancel-btn, .stop-btn');
        if (quickCancel) {
            page.once('dialog', async dialog => {
                await dialog.accept();
            });

            await quickCancel.click();
            log('✅ Immediate cancellation tested', 'success');
        }

        log('\n✅ Research cancellation test completed successfully!', 'success');

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

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

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