/**
 * DEV-ONLY TEST FILE -- not loaded by the app, safe to delete from a
 * production deployment. Simulates a real sidebar click + AJAX swap using
 * jsdom, so ajax-nav.js's logic can be checked without a real browser.
 *
 * To run: from this directory, `npm install jsdom` then `node test_ajax_nav.js`
 */
const { JSDOM } = require('jsdom');
const fs = require('fs');

const currentPageHtml = `
<!DOCTYPE html><html><head><title>Dashboard</title>
<link rel="stylesheet" href="/ivm/public/components/sidebar.css">
</head>
<body>
  <div id="sidebar" data-marker="ORIGINAL-SIDEBAR-INSTANCE">
    <div id="attendance-sub" class="hidden">
      <a href="/ivm/public/attendance.php" class="text-slate-600">Daily Logs</a>
    </div>
    <a href="/ivm/public/dashboard.php" class="bg-indigo-50 text-indigo-700 font-bold active">Dashboard</a>
    <a href="/ivm/public/attendance.php" class="text-slate-600">Attendance (top link)</a>
    <a href="https://example.com/external" >External</a>
    <a href="/ivm/public/logout.php">Logout</a>
    <a href="#" id="hash-link">Hash link</a>
  </div>
  <div id="main-content" class="flex-1 min-w-0 md:pl-64 original-class">
    <h1>Dashboard content</h1>
  </div>
  <script src="/ivm/public/components/sidebar.js"></script>
  <script>window.__dashboardScriptRan = true;</script>
</body></html>`;

const fetchedPageHtml = `
<!DOCTYPE html><html><head><title>Attendance</title>
<link rel="stylesheet" href="/ivm/public/components/sidebar.css">
<script src="/ivm/public/components/fake-chart-lib.js"></script>
</head>
<body>
  <div id="sidebar" data-marker="FETCHED-SIDEBAR-INSTANCE">
    <div id="attendance-sub" class="hidden">
      <a href="/ivm/public/attendance.php" class="text-indigo-600 font-bold bg-indigo-50/80">Daily Logs</a>
    </div>
    <a href="/ivm/public/dashboard.php" class="text-slate-700">Dashboard</a>
    <a href="/ivm/public/attendance.php" class="bg-indigo-50 text-indigo-700 font-bold active">Attendance (top link)</a>
  </div>
  <div id="main-content" class="flex-1 min-w-0 md:pl-64 fetched-class">
    <h1>Attendance content</h1>
  </div>
  <script>window.__attendanceScriptRan = true;</script>
</body></html>`;

async function main() {
  const dom = new JSDOM(currentPageHtml, {
    url: 'https://web.example.com/ivm/public/dashboard.php',
    runScripts: 'dangerously',
    pretendToBeVisual: true
  });

  const { window } = dom;

  // jsdom (by default, without a resource loader) never actually loads
  // dynamically-inserted <script src> elements, so it will never fire their
  // load/error handlers on its own. Simulate an instant successful load for
  // any script we recognize, so we can test the promise-chaining logic
  // without depending on real network access.
  const observer = new window.MutationObserver((mutations) => {
    mutations.forEach((m) => {
      m.addedNodes.forEach((node) => {
        if (node.tagName === 'SCRIPT' && node.src) {
          if (node.src.includes('fake-chart-lib.js')) {
            window.__fakeChartLibLoaded = true;
          }
          setTimeout(() => { if (typeof node.onload === 'function') node.onload(); }, 0);
        }
      });
    });
  });
  observer.observe(window.document.documentElement, { childList: true, subtree: true });

  // Stub CSS.escape (present in browsers, sometimes missing in jsdom)
  if (!window.CSS) window.CSS = {};
  if (!window.CSS.escape) window.CSS.escape = (s) => s.replace(/["\\]/g, '\\$&');

  let fetchCalledWith = null;
  window.fetch = (url, opts) => {
    fetchCalledWith = { url, opts };
    return Promise.resolve({
      ok: true,
      redirected: false,
      url: 'https://web.example.com/ivm/public/attendance.php',
      text: () => Promise.resolve(fetchedPageHtml)
    });
  };

  const pushedStates = [];
  window.history.pushState = (state, title, url) => { pushedStates.push(url); };

  const src = fs.readFileSync(__dirname + '/ajax-nav.js', 'utf8');
  window.eval(src);

  const results = {};

  // --- Test 1: clicking an eligible sidebar link triggers fetch + swap ---
  const attendanceLink = window.document.querySelector('#sidebar a[href="/ivm/public/attendance.php"]');
  const clickEvent = new window.MouseEvent('click', { bubbles: true, cancelable: true, button: 0 });
  attendanceLink.dispatchEvent(clickEvent);

  results.defaultPrevented = clickEvent.defaultPrevented;
  results.fetchCalled = !!fetchCalledWith;
  const fetchUrlDiagnostic = fetchCalledWith && fetchCalledWith.url;
  results.fetchUrlCorrect = fetchUrlDiagnostic === 'https://web.example.com/ivm/public/attendance.php';

  // wait for the promise chain (fetch -> text -> parse -> script exec) to settle
  await new Promise((r) => setTimeout(r, 300));

  results.mainContentSwapped = window.document.getElementById('main-content').innerHTML.includes('Attendance content');
  results.mainContentClassPreserved = window.document.getElementById('main-content').className.includes('fetched-class');
  results.titleUpdated = window.document.title === 'Attendance';
  results.historyPushed = pushedStates.includes('https://web.example.com/ivm/public/attendance.php');
  results.sidebarNotReplaced = window.document.getElementById('sidebar').getAttribute('data-marker') === 'ORIGINAL-SIDEBAR-INSTANCE';
  results.activeClassSynced = window.document.getElementById('attendance-sub')
    .querySelector('a[href="/ivm/public/attendance.php"]').className.includes('text-indigo-600');
  results.topLevelActiveClassSynced = Array.prototype.find.call(
    window.document.querySelectorAll('#sidebar > a[href="/ivm/public/attendance.php"]'),
    () => true
  ).className.includes('active');
  results.dashboardLinkDeactivated = window.document.querySelector('#sidebar a[href="/ivm/public/dashboard.php"]').className.includes('text-slate-700');
  results.submenuExpanded = !window.document.getElementById('attendance-sub').classList.contains('hidden');
  results.newInlineScriptRan = window.__attendanceScriptRan === true;
  results.oldInlineScriptStillThere = window.__dashboardScriptRan === true; // shouldn't be wiped
  results.headScriptInjectedAndLoaded = window.__fakeChartLibLoaded === true;
  results.overlayCleanedUp = !window.document.querySelector('[data-ajax-nav-overlay]');
  results.progressBarPresent = !!window.document.getElementById('ajax-nav-progress');

  // --- Test 2: external link is ignored (not intercepted) ---
  fetchCalledWith = null;
  const externalLink = window.document.querySelector('#sidebar a[href^="https://example.com"]');
  const ev2 = new window.MouseEvent('click', { bubbles: true, cancelable: true, button: 0 });
  externalLink.dispatchEvent(ev2);
  results.externalLinkNotIntercepted = !ev2.defaultPrevented && fetchCalledWith === null;

  // --- Test 3: logout link is ignored (not intercepted) ---
  const logoutLink = window.document.querySelector('#sidebar a[href$="logout.php"]');
  const ev3 = new window.MouseEvent('click', { bubbles: true, cancelable: true, button: 0 });
  logoutLink.dispatchEvent(ev3);
  results.logoutNotIntercepted = !ev3.defaultPrevented && fetchCalledWith === null;

  // --- Test 4: hash link is ignored (ajax-nav shouldn't fetch for it) ---
  fetchCalledWith = null;
  const hashLink = window.document.getElementById('hash-link');
  const ev4 = new window.MouseEvent('click', { bubbles: true, cancelable: true, button: 0 });
  hashLink.dispatchEvent(ev4);
  results.hashLinkNotIntercepted = fetchCalledWith === null;

  console.log(JSON.stringify(results, null, 2));

  const failed = Object.entries(results).filter(([k, v]) => v !== true);
  if (failed.length) {
    console.error('FAILED CHECKS:', failed.map(([k]) => k));
    process.exit(1);
  } else {
    console.log('ALL CHECKS PASSED');
  }
}

main().catch((e) => { console.error(e); process.exit(1); });
