// Headless guard for the trace-chart viewer's keyboard-control math (keyXRange).
//
// keyXRange is PURE: given a key + the current x-range [lo,hi] + the zoom anchor (the
// x-value to keep fixed, i.e. the cursor position) + the data extent [first,last], it
// returns the next {min,max} — or null for a non-chart key. The load-bearing property is
// "zoom toward the cursor": the anchor keeps its RELATIVE position in the new range, so
// the point under the mouse stays put. A regression that zoomed around the centre instead
// would still shrink the range but slide the cursor's point — caught here by an anchor
// off-centre (anchor=2 in a [0,10] range). Arrows pan by 15% of the span; 0/Home reset to
// the extent. Drives the pure export; no DOM/uPlot.
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";

const require = createRequire(import.meta.url);
const here = dirname(fileURLToPath(import.meta.url));

const fail = (msg) => { console.error("FAIL: " + msg); process.exit(1); };
const close = (a, b) => Math.abs(a - b) < 1e-9;
const eqRange = (r, min, max, msg) => {
  if (!r || !close(r.min, min) || !close(r.max, max)) fail(`${msg} (got ${JSON.stringify(r)}, want {min:${min},max:${max}})`);
};

// No document / no AURA_TRACES -> the IIFE's browser mount is skipped; we get the export.
global.window = {};
const { keyXRange } = require(join(here, "..", "assets", "chart-viewer.js"));

// lo=0, hi=10 (span 10), anchor=2 (off-centre, left), full extent [0, 99].
const lo = 0, hi = 10, anchor = 2, ext = [0, 99];

// pan: 15% of span = 1.5, span preserved.
eqRange(keyXRange("ArrowLeft", lo, hi, anchor, ext), -1.5, 8.5, "ArrowLeft pans left by 15% of the span");
eqRange(keyXRange("ArrowRight", lo, hi, anchor, ext), 1.5, 11.5, "ArrowRight pans right by 15% of the span");

// zoom in (factor 0.8) toward anchor=2 -> newLo=0.4, newHi=8.4 (span 8).
const zin = keyXRange("+", lo, hi, anchor, ext);
eqRange(zin, 0.4, 8.4, "+ zooms in toward the anchor");
if (!close((anchor - zin.min) / (zin.max - zin.min), (anchor - lo) / (hi - lo)))
  fail("+ must keep the anchor at the same relative position (zoom toward cursor, not centre)");
eqRange(keyXRange("=", lo, hi, anchor, ext), 0.4, 8.4, "= aliases + (zoom in)");

// zoom out (factor 1.25) toward anchor=2 -> newLo=-0.5, newHi=12.
eqRange(keyXRange("-", lo, hi, anchor, ext), -0.5, 12, "- zooms out toward the anchor");
eqRange(keyXRange("_", lo, hi, anchor, ext), -0.5, 12, "_ aliases - (zoom out)");

// reset to the full data extent.
eqRange(keyXRange("0", lo, hi, anchor, ext), 0, 99, "0 resets to the data extent");
eqRange(keyXRange("Home", lo, hi, anchor, ext), 0, 99, "Home resets to the data extent");

// a non-chart key is ignored.
if (keyXRange("q", lo, hi, anchor, ext) !== null) fail("a non-chart key must return null");

console.log("OK — keyboard pan / zoom-toward-cursor / reset math; non-chart keys ignored.");
process.exit(0);
