#!/usr/bin/env node
/**
 * Mobile Fixes Verification Test
 *
 * Purpose: Verify mobile CSS fixes work correctly on small phone viewports
 * Tests: News, Results, Library, and main research page
 * Viewports: 360px (small Android), 375px (iPhone SE)
 *
 * Usage: node test_mobile_fixes_verification.js
 */

const puppeteer = require('puppeteer');
const path = require('path');
const fs = require('fs').promises;

// Test devices - focus on SMALL phones
const DEVICES = {
    'Small_Android_360': {
        width: 360,
        height: 640,
        deviceScaleFactor: 2,
        isMobile: true,
        hasTouch: true
    },
    'iPhone_SE_375': {
        width: 375,
        height: 667,
        deviceScaleFactor: 2,
        isMobile: true,
        hasTouch: true
    },
    'iPhone_14_430': {
        width: 430,
        height: 932,
        deviceScaleFactor: 3,
        isMobile: true,
        hasTouch: true
    }
};

// Pages to test (focus on fixed pages)
const PAGES = [
    { path: '/', name: 'Research_Main' },
    { path: '/news/', name: 'News' },
    { path: '/library/', name: 'Library' },
    { path: '/history/', name: 'History' },
    { path: '/settings/', name: 'Settings' },
];

class MobileFixesTest {
    constructor() {
        this.baseUrl = process.env.TEST_BASE_URL || 'http://127.0.0.1:5000';
        this.timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
        this.outputDir = path.join(__dirname, 'mobile-fixes-screenshots', this.timestamp);
        this.results = [];
        this.passed = 0;
        this.failed = 0;
    }

    async run() {
        console.log('📱 Mobile Fixes Verification Test');
        console.log('='.repeat(60));
        console.log(`📁 Output: ${this.outputDir}`);
        console.log('='.repeat(60));

        await fs.mkdir(this.outputDir, { recursive: true });

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

            for (const [deviceName, viewport] of Object.entries(DEVICES)) {
                await this.testDevice(browser, deviceName, viewport);
            }

            await this.generateReport();
            console.log('\n' + '='.repeat(60));
            console.log(`✅ Tests passed: ${this.passed}`);
            console.log(`❌ Tests failed: ${this.failed}`);
            console.log(`📁 Screenshots: ${this.outputDir}`);
            console.log('='.repeat(60));

            // Exit with error code if any failures
            process.exit(this.failed > 0 ? 1 : 0);

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

    async testDevice(browser, deviceName, viewport) {
        console.log(`\n📱 Testing ${deviceName} (${viewport.width}x${viewport.height})`);
        console.log('─'.repeat(50));

        const deviceDir = path.join(this.outputDir, deviceName);
        await fs.mkdir(deviceDir, { recursive: true });

        const page = await browser.newPage();
        await page.setViewport(viewport);

        // Try to authenticate
        try {
            await this.authenticate(page);
            console.log('  ✅ Authenticated');
        } catch (error) {
            console.log('  ⚠️ Auth failed, testing public pages:', error.message);
        }

        for (const pageInfo of PAGES) {
            await this.testPage(page, deviceName, deviceDir, pageInfo, viewport);
        }

        await page.close();
    }

    async authenticate(page) {
        // Go to login page
        await page.goto(`${this.baseUrl}/auth/login`, { waitUntil: 'networkidle2', timeout: 30000 });

        // Check if already logged in
        const url = page.url();
        if (!url.includes('/auth/login')) {
            return; // Already authenticated
        }

        // Try to login with test credentials
        const username = process.env.TEST_USERNAME || 'test@example.com';
        const password = process.env.TEST_PASSWORD || 'testpassword';

        await page.type('input[name="email"], input[name="username"], #email, #username', username);
        await page.type('input[name="password"], #password', password);
        await page.click('button[type="submit"]');
        await page.waitForNavigation({ waitUntil: 'networkidle2', timeout: 10000 }).catch(() => {});
    }

    async testPage(page, deviceName, deviceDir, pageInfo, viewport) {
        console.log(`  📄 ${pageInfo.name}...`);

        const result = {
            device: deviceName,
            page: pageInfo.name,
            viewport,
            issues: [],
            screenshot: null
        };

        try {
            await page.goto(this.baseUrl + pageInfo.path, {
                waitUntil: 'networkidle2',
                timeout: 30000
            });

            // Wait for mobile nav and page to settle
            await new Promise(resolve => setTimeout(resolve, 1500));

            // Run diagnostic checks
            const diagnostics = await page.evaluate(() => {
                const issues = [];

                // Check for horizontal scroll (most critical mobile issue)
                const hasHorizontalScroll = document.documentElement.scrollWidth > window.innerWidth;
                if (hasHorizontalScroll) {
                    issues.push({
                        type: 'HORIZONTAL_SCROLL',
                        severity: 'HIGH',
                        message: `Page has horizontal scroll: ${document.documentElement.scrollWidth}px > ${window.innerWidth}px`
                    });

                    // Find elements causing overflow
                    const overflowingElements = [];
                    document.querySelectorAll('*').forEach(el => {
                        const rect = el.getBoundingClientRect();
                        if (rect.right > window.innerWidth + 5) {
                            overflowingElements.push({
                                tag: el.tagName,
                                class: el.className,
                                width: rect.width,
                                overflow: rect.right - window.innerWidth
                            });
                        }
                    });

                    if (overflowingElements.length > 0) {
                        issues.push({
                            type: 'OVERFLOW_ELEMENTS',
                            severity: 'HIGH',
                            message: `${overflowingElements.length} elements overflow viewport`,
                            details: overflowingElements.slice(0, 5)
                        });
                    }
                }

                // Check sidebar visibility (should be hidden on mobile)
                const sidebar = document.querySelector('.ldr-sidebar');
                if (sidebar) {
                    const sidebarStyle = window.getComputedStyle(sidebar);
                    if (sidebarStyle.display !== 'none' && sidebarStyle.visibility !== 'hidden') {
                        issues.push({
                            type: 'SIDEBAR_VISIBLE',
                            severity: 'MEDIUM',
                            message: 'Desktop sidebar is visible on mobile'
                        });
                    }
                }

                // Check mobile nav visibility
                const mobileNav = document.querySelector('.ldr-mobile-bottom-nav');
                if (mobileNav) {
                    const navStyle = window.getComputedStyle(mobileNav);
                    if (navStyle.display === 'none') {
                        issues.push({
                            type: 'MOBILE_NAV_HIDDEN',
                            severity: 'MEDIUM',
                            message: 'Mobile navigation is hidden'
                        });
                    }
                }

                // Check touch targets (44px minimum)
                const smallButtons = [];
                document.querySelectorAll('button, a.btn, [role="button"]').forEach(btn => {
                    const rect = btn.getBoundingClientRect();
                    if (rect.width > 0 && rect.height > 0 && (rect.width < 40 || rect.height < 40)) {
                        smallButtons.push({
                            text: btn.textContent.trim().substring(0, 30),
                            size: `${Math.round(rect.width)}x${Math.round(rect.height)}`
                        });
                    }
                });

                if (smallButtons.length > 3) {
                    issues.push({
                        type: 'SMALL_TOUCH_TARGETS',
                        severity: 'LOW',
                        message: `${smallButtons.length} buttons below 44px touch target`,
                        details: smallButtons.slice(0, 5)
                    });
                }

                // Check text readability
                const tooSmallText = [];
                document.querySelectorAll('p, span, label, button, a').forEach(el => {
                    const style = window.getComputedStyle(el);
                    const fontSize = parseFloat(style.fontSize);
                    if (fontSize > 0 && fontSize < 12 && el.textContent.trim()) {
                        tooSmallText.push({
                            tag: el.tagName,
                            text: el.textContent.trim().substring(0, 20),
                            size: fontSize
                        });
                    }
                });

                if (tooSmallText.length > 5) {
                    issues.push({
                        type: 'SMALL_TEXT',
                        severity: 'LOW',
                        message: `${tooSmallText.length} elements with text < 12px`,
                        details: tooSmallText.slice(0, 5)
                    });
                }

                return {
                    issues,
                    pageWidth: document.documentElement.scrollWidth,
                    viewportWidth: window.innerWidth
                };
            });

            result.issues = diagnostics.issues;
            result.pageWidth = diagnostics.pageWidth;
            result.viewportWidth = diagnostics.viewportWidth;

            // Take screenshot
            const screenshotPath = path.join(deviceDir, `${pageInfo.name}.png`);
            await page.screenshot({ path: screenshotPath, fullPage: true });
            result.screenshot = screenshotPath;

            // Report results
            const hasHighIssues = result.issues.some(i => i.severity === 'HIGH');
            if (hasHighIssues) {
                console.log(`    ❌ FAILED - ${result.issues.filter(i => i.severity === 'HIGH').length} critical issues`);
                result.issues.filter(i => i.severity === 'HIGH').forEach(i => {
                    console.log(`       • ${i.message}`);
                });
                this.failed++;
            } else {
                const mediumIssues = result.issues.filter(i => i.severity === 'MEDIUM').length;
                const lowIssues = result.issues.filter(i => i.severity === 'LOW').length;
                if (mediumIssues > 0 || lowIssues > 0) {
                    console.log(`    ⚠️ PASSED with warnings (${mediumIssues} medium, ${lowIssues} low)`);
                } else {
                    console.log(`    ✅ PASSED`);
                }
                this.passed++;
            }

        } catch (error) {
            console.log(`    ❌ ERROR: ${error.message}`);
            result.issues.push({
                type: 'ERROR',
                severity: 'HIGH',
                message: error.message
            });
            this.failed++;
        }

        this.results.push(result);
    }

    async generateReport() {
        // Generate JSON report
        const jsonPath = path.join(this.outputDir, 'report.json');
        await fs.writeFile(jsonPath, JSON.stringify(this.results, null, 2));

        // Generate HTML report
        const html = `<!DOCTYPE html>
<html>
<head>
    <title>Mobile Fixes Verification Report</title>
    <style>
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 20px; background: #1a1a2e; color: #eee; }
        h1 { color: #4ecca3; }
        .device { margin: 20px 0; padding: 20px; background: #16213e; border-radius: 8px; }
        .device h2 { color: #4ecca3; margin-top: 0; }
        .page { margin: 10px 0; padding: 15px; background: #0f3460; border-radius: 4px; }
        .page img { max-width: 300px; border: 1px solid #4ecca3; margin-top: 10px; }
        .passed { border-left: 4px solid #4ecca3; }
        .failed { border-left: 4px solid #e94560; }
        .issue { padding: 5px 10px; margin: 5px 0; border-radius: 3px; }
        .issue.HIGH { background: #e94560; }
        .issue.MEDIUM { background: #ff9a00; color: #000; }
        .issue.LOW { background: #4ecca3; color: #000; }
        .summary { padding: 20px; background: #16213e; border-radius: 8px; margin-bottom: 20px; }
        .summary .passed { color: #4ecca3; font-size: 24px; }
        .summary .failed { color: #e94560; font-size: 24px; }
    </style>
</head>
<body>
    <h1>📱 Mobile Fixes Verification Report</h1>
    <p>Generated: ${new Date().toISOString()}</p>

    <div class="summary">
        <span class="passed">✅ Passed: ${this.passed}</span> |
        <span class="failed">❌ Failed: ${this.failed}</span>
    </div>

    ${Object.keys(DEVICES).map(device => `
        <div class="device">
            <h2>📱 ${device} (${DEVICES[device].width}x${DEVICES[device].height})</h2>
            ${this.results.filter(r => r.device === device).map(r => `
                <div class="page ${r.issues.some(i => i.severity === 'HIGH') ? 'failed' : 'passed'}">
                    <strong>${r.page}</strong>
                    ${r.issues.length > 0 ? `
                        <div class="issues">
                            ${r.issues.map(i => `<div class="issue ${i.severity}">${i.severity}: ${i.message}</div>`).join('')}
                        </div>
                    ` : '<div style="color:#4ecca3">No issues</div>'}
                    ${r.screenshot ? `<br><img src="${r.device}/${r.page}.png" alt="${r.page}">` : ''}
                </div>
            `).join('')}
        </div>
    `).join('')}
</body>
</html>`;

        const htmlPath = path.join(this.outputDir, 'report.html');
        await fs.writeFile(htmlPath, html);
    }
}

// Run the test
const test = new MobileFixesTest();
test.run().catch(error => {
    console.error('Test failed:', error);
    process.exit(1);
});
