/**
 * Auth helper for pytest tests
 * Uses Puppeteer to authenticate and save cookies
 */

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

async function authenticate(baseUrl, username, password, cookieFile) {
    console.log(`Starting authentication for ${username} at ${baseUrl}`);
    const browser = await puppeteer.launch(getPuppeteerLaunchOptions());

    try {
        const page = await browser.newPage();

        // Set longer timeout for CI environments
        page.setDefaultTimeout(120000); // 120 seconds
        page.setDefaultNavigationTimeout(120000);

        // Go to login page
        console.log('Navigating to login page...');
        await page.goto(`${baseUrl}/auth/login`, {
            waitUntil: 'networkidle0',
            timeout: 60000
        });
        console.log('Login page loaded');

        // Check if we need to register
        console.log('Checking for register link...');
        const registerLink = await page.$('a[href="/auth/register"]');
        if (registerLink) {
            console.log('Register link found, clicking...');
            await registerLink.click();
            await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 60000 });

            // Wait for registration form
            await page.waitForSelector('#username', { timeout: 5000 });

            // Fill registration form
            await page.type('#username', username);
            await page.type('#password', password);
            await page.type('#confirm_password', password);

            // Check for acknowledge checkbox
            const acknowledgeCheckbox = await page.$('input[name="acknowledge"]');
            if (acknowledgeCheckbox) {
                console.log('Clicking acknowledge checkbox...');
                await page.click('input[name="acknowledge"]');
            }

            // Submit
            console.log('Submitting registration form...');

            // Click and wait for navigation
            await Promise.all([
                page.click('button[type="submit"]'),
                page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 60000 }).catch(e => {
                    console.log('Navigation wait error:', e.message);
                    // If navigation fails, wait a bit for the page to process
                    return page.waitForTimeout(3000);
                })
            ]);

            // Check if we're still on the registration page
            const currentUrl = page.url();
            if (currentUrl.includes('/auth/register')) {
                // Check for errors
                const error = await page.$('.alert-danger, .error-message');
                if (error) {
                    const errorText = await page.evaluate(el => el.textContent, error);
                    if (errorText.includes('already exists')) {
                        console.log('User already exists, will try login');
                        // Don't throw, we'll try login next
                    } else {
                        throw new Error(`Registration failed: ${errorText}`);
                    }
                } else {
                    // Wait a bit more for redirect - but don't fail if no navigation happens
                    await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 5000 }).catch(_e => {
                        console.log('No navigation after registration, continuing...');
                    });
                }
            }
            console.log('Registration completed');
        } else {
            // Try login
            await page.waitForSelector('#username', { timeout: 5000 });
            await page.type('#username', username);
            await page.type('#password', password);
            console.log('Submitting login form...');

            // Click and wait for navigation
            await Promise.all([
                page.click('button[type="submit"]'),
                page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 60000 }).catch(e => {
                    console.log('Navigation wait error:', e.message);
                    return page.waitForTimeout(3000);
                })
            ]);
            console.log('Login completed');
        }

        // After login/registration, navigate to home page to ensure we have CSRF token
        const currentUrl = page.url();
        if (!currentUrl.includes('/auth/')) {
            console.log('Already on app page, good for CSRF token');
        } else {
            console.log('Navigating to home page to get CSRF token...');
            await page.goto(baseUrl, { waitUntil: 'networkidle0', timeout: 30000 });
        }

        // Get cookies
        const cookies = await page.cookies();
        console.log(`Got ${cookies.length} cookies`);

        // Log cookie names for debugging
        const cookieNames = cookies.map(c => c.name);
        console.log('Cookie names:', cookieNames.join(', '));

        // Try to get CSRF token - Flask-WTF doesn't use cookies for CSRF, it uses session
        // We need to get it from the page
        let csrfToken = null;

        console.log('Getting CSRF token from page meta tag...');
        try {
            csrfToken = await page.evaluate(() => {
                const metaTag = document.querySelector('meta[name="csrf-token"]');
                return metaTag ? metaTag.getAttribute('content') : null;
            });

            if (!csrfToken) {
                // Try to find it in a form
                csrfToken = await page.evaluate(() => {
                    const csrfInput = document.querySelector('input[name="csrf_token"]');
                    return csrfInput ? csrfInput.value : null;
                });
            }

            if (csrfToken) {
                console.log('Found CSRF token:', csrfToken.substring(0, 10) + '...');
                // Add it as a cookie for compatibility with the test framework
                cookies.push({
                    name: 'csrf_token',
                    value: csrfToken,
                    domain: new URL(baseUrl).hostname,
                    path: '/',
                    httpOnly: false,
                    secure: false,
                    sameSite: 'Lax'
                });
            } else {
                console.log('WARNING: Could not find CSRF token on page');
            }
        } catch (e) {
            console.log('Error getting CSRF token from page:', e.message);
        }

        // Save to file
        fs.writeFileSync(cookieFile, JSON.stringify(cookies, null, 2));

        console.log('Authentication successful');

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

// Get arguments
const [baseUrl, username, password, cookieFile] = process.argv.slice(2);

if (!baseUrl || !username || !password || !cookieFile) {
    console.error('Usage: node auth_helper.js <baseUrl> <username> <password> <cookieFile>');
    process.exit(1);
}

authenticate(baseUrl, username, password, cookieFile)
    .then(() => {
        process.exit(0);
    })
    .catch(err => {
        console.error('Authentication failed:', err);
        console.error('Stack trace:', err.stack);
        process.exit(1);
    });
