/**
 * Console-error crawler using Playwright.
 * Logs in, visits all sidebar nav links, reports JS errors/exceptions.
 *
 * Usage:
 *   npm install -D @playwright/test && npx playwright install chromium
 *   node scripts/console-check.mjs
 */

// Self-re-exec with playwright system deps on Linux if needed
if (process.platform === 'linux' && !process.env.__PW_ENV_OK) {
    const { existsSync } = await import('fs');
    const depsDir = `${process.env.HOME}/.local/lib/playwright-deps`;
    if (existsSync(depsDir)) {
        const { spawnSync } = await import('child_process');
        const ld = process.env.LD_LIBRARY_PATH ?? '';
        const result = spawnSync(process.execPath, process.argv.slice(1), {
            env: { ...process.env, LD_LIBRARY_PATH: ld ? `${depsDir}:${ld}` : depsDir, __PW_ENV_OK: '1' },
            stdio: 'inherit',
        });
        process.exit(result.status ?? 1);
    }
}

import { chromium } from '@playwright/test';
import { readFileSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';

const __dir = dirname(fileURLToPath(import.meta.url));
const projectRoot = resolve(__dir, '..');

function readEnv() {
    try {
        return Object.fromEntries(
            readFileSync(resolve(projectRoot, '.env'), 'utf8')
                .split('\n')
                .filter(l => l && !l.startsWith('#') && l.includes('='))
                .map(l => { const i = l.indexOf('='); return [l.slice(0, i).trim(), l.slice(i + 1).trim()]; })
        );
    } catch { return {}; }
}
const env = readEnv();

const BASE  = process.env.APP_URL       ?? env.APP_URL ?? 'https://app.nimuli.com';
const EMAIL = process.env.TEST_EMAIL    ?? 'nexxo@nimuli.com';
const PASS  = process.env.TEST_PASSWORD ?? 'NimuliDev2026!';

const errors = [];
const warnings = [];

console.log(`\n${'═'.repeat(45)}`);
console.log('  Nimuli — Console Error Check');
console.log(`  ${new Date().toISOString()}`);
console.log(`  Base: ${BASE}`);
console.log(`${'═'.repeat(45)}\n`);

const browser = await chromium.launch({
    headless: true,
    args: [
        '--no-sandbox', '--disable-setuid-sandbox', '--disable-gpu',
        '--disable-dev-shm-usage', '--in-process-gpu',
        '--disable-features=VizDisplayCompositor',
    ],
});
const ctx = await browser.newContext({
    ignoreHTTPSErrors: true,
    viewport: { width: 1280, height: 800 },
});
const page = await ctx.newPage();

page.on('console', msg => {
    if (msg.type() === 'error') {
        errors.push({ url: page.url(), text: msg.text() });
    } else if (msg.type() === 'warning') {
        warnings.push({ url: page.url(), text: msg.text() });
    }
});
page.on('pageerror', err => {
    errors.push({ url: page.url(), text: `PageError: ${err.message}` });
});

// ── Login ────────────────────────────────────
console.log('[ LOGIN ]');
await page.goto(`${BASE}/login`, { waitUntil: 'networkidle' });
await page.fill('input[name=email]', EMAIL);
await page.fill('input[name=password]', PASS);
await page.click('button[type=submit]');
await page.waitForLoadState('networkidle');
console.log(`  ✓ Logged in: ${page.url()}`);

// ── Collect nav links ─────────────────────────
const navLocators = page.locator('[data-nav-link]');
const navCount = await navLocators.count();
const navLinks = [];
for (let i = 0; i < navCount; i++) {
    const href = await navLocators.nth(i).getAttribute('href');
    if (href && !href.endsWith('#') && !navLinks.includes(href)) {
        navLinks.push(href);
    }
}

console.log(`\n[ CRAWLING ${navLinks.length} NAV LINKS ]`);

for (const link of navLinks) {
    const pre = errors.length;
    await page.goto(link, { waitUntil: 'networkidle' });
    await page.waitForTimeout(400);
    const newErrs = errors.length - pre;
    const status = newErrs > 0 ? `✗ ${newErrs} new error(s)` : '✓ clean';
    let path = link;
    try { path = new URL(link).pathname; } catch { /* keep full link */ }
    console.log(`  ${status}: ${path}`);
}

// ── Profile pages ─────────────────────────────
console.log('\n[ PROFILE PAGES ]');
for (const path of ['/profile', '/profile/personal', '/profile/preferences', '/profile/security']) {
    const pre = errors.length;
    await page.goto(`${BASE}${path}`, { waitUntil: 'networkidle' });
    await page.waitForTimeout(300);
    const newErrs = errors.length - pre;
    console.log(`  ${newErrs > 0 ? '✗' : '✓'} ${path}`);
}

await browser.close();

// ── Report ────────────────────────────────────
console.log(`\n${'═'.repeat(45)}`);
if (errors.length > 0) {
    console.error(`  ❌ ${errors.length} console error(s):`);
    for (const e of errors) {
        let path = e.url;
        try { path = new URL(e.url).pathname; } catch { /* keep full */ }
        console.error(`     ${path}: ${e.text.slice(0, 140)}`);
    }
    console.error(`${'═'.repeat(45)}\n`);
    process.exit(1);
}
if (warnings.length > 0) {
    console.warn(`  ⚠  ${warnings.length} console warning(s) (non-blocking)`);
}
console.log('  ✅ No console errors');
console.log(`${'═'.repeat(45)}\n`);
