/**
 * Navigation health test for the cPad Control Panel.
 *
 * Two operating modes:
 *
 *  1. Dynamic  — reads tests/.discovered/cpad-links.json (written by
 *                navigation-discovery.spec.ts) and visits every link.
 *                Run the discovery spec first to populate this file.
 *
 *  2. Fallback — when the discovery file is absent, falls back to a static
 *                list of known /cp routes so the suite never fails silently.
 *
 * For every visited page the test asserts:
 *   • No redirect to /cp/login (i.e. session is still valid)
 *   • HTTP status not 5xx (detected via response interception)
 *   • No uncaught JavaScript exceptions
 *   • No browser console errors
 *   • Page body is visible and non-empty
 *   • Page does not contain Laravel error text
 *
 * Run:
 *   npx playwright test tests/cpad/navigation.spec.ts --project=cpad
 */

import { test, expect } from '@playwright/test';
import { CP_PATH, attachErrorListeners } from '../helpers/auth';
import { hasForm } from '../helpers/formFiller';
import fs from 'fs';
import path from 'path';

// ─────────────────────────────────────────────────────────────────────────────
// Link source
// ─────────────────────────────────────────────────────────────────────────────

const DISCOVERED_FILE = path.join('tests', '.discovered', 'cpad-links.json');

/** Well-known /cp pages used when the discovery file is missing */
const STATIC_FALLBACK_LINKS: string[] = [
  '/cp/dashboard',
  '/cp/configuration',
  '/cp/config',
  '/cp/language/app',
  '/cp/language/system',
  '/cp/translation/app',
  '/cp/security/access',
  '/cp/security/roles',
  '/cp/security/permissions',
  '/cp/security/login',
  '/cp/plugins',
  '/cp/user/profile',
  '/cp/messages',
  '/cp/api/keys',
  '/cp/friendly-url',
];

function loadLinks(): string[] {
  if (fs.existsSync(DISCOVERED_FILE)) {
    try {
      const links: string[] = JSON.parse(fs.readFileSync(DISCOVERED_FILE, 'utf8'));
      if (links.length > 0) return links;
    } catch { /* fall through to static list */ }
  }
  console.warn('[navigation] discovery file not found — using static fallback list');
  return STATIC_FALLBACK_LINKS;
}

const CP_LINKS = loadLinks();

// ─────────────────────────────────────────────────────────────────────────────
// Main navigation suite
// ─────────────────────────────────────────────────────────────────────────────

test.describe('cPad Navigation Health', () => {
  for (const linkPath of CP_LINKS) {
    test(`page loads: ${linkPath}`, async ({ page }) => {
      const { consoleErrors, networkErrors } = attachErrorListeners(page);

      await page.goto(linkPath);
      await page.waitForLoadState('networkidle', { timeout: 20_000 });

      // ── Auth check ──────────────────────────────────────────────────────
      expect(page.url(), `${linkPath} should not redirect to login`).not.toContain('/login');

      // ── HTTP errors ─────────────────────────────────────────────────────
      expect(networkErrors.length, `HTTP 5xx on ${linkPath}: ${networkErrors.join(' | ')}`).toBe(0);

      // ── Body visibility ─────────────────────────────────────────────────
      await expect(page.locator('body')).toBeVisible();

      const bodyText = await page.locator('body').textContent() ?? '';
      expect(bodyText.trim().length, `Body should not be empty on ${linkPath}`).toBeGreaterThan(0);

      // ── Laravel / server error page ──────────────────────────────────────
      const hasServerError = /Whoops[,!]|Server Error|Call to undefined function|SQLSTATE/.test(bodyText);
      expect(hasServerError, `Server/Laravel error page at ${linkPath}: ${bodyText.slice(0, 200)}`).toBe(false);

      // ── JS exceptions ────────────────────────────────────────────────────
      expect(consoleErrors.length, `JS console errors on ${linkPath}: ${consoleErrors.join(' | ')}`).toBe(0);

      // ── Form detection (informational — logged, not asserted) ─────────────
      const pageHasForm = await hasForm(page);
      if (pageHasForm) {
        console.log(`  [form] form detected on ${linkPath}`);
      }
    });
  }
});
