"use strict";

const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");
const test = require("node:test");
const vm = require("node:vm");

const root = path.resolve(__dirname, "..", "..");
const app = fs.readFileSync(path.join(
  root,
  "src",
  "MBN_STOCK_WEBVIEW.LegacyParityApp",
  "Web",
  "app.js"), "utf8");
const nativeWindow = fs.readFileSync(path.join(
  root,
  "src",
  "MBN_STOCK_WEBVIEW.LegacyParityApp",
  "MainWindow.xaml.cs"), "utf8");
const nativePlayout = fs.readFileSync(path.join(
  root,
  "src",
  "MBN_STOCK_WEBVIEW.LegacyParityApp",
  "MainWindow.Playout.cs"), "utf8");

function loadCutHelpers(rows) {
  const start = app.indexOf("function legacyCutKey");
  const end = app.indexOf("function createCutElement", start);
  assert.ok(start >= 0 && end > start);
  const context = {
    cutList: { children: rows },
    result: null
  };
  vm.runInNewContext(`
    ${app.slice(start, end)}
    result = { legacyCutKey, focusCutElement, cutKeyboardTarget };
  `, context);
  return context.result;
}

function row(id) {
  return {
    id,
    tabIndex: -1,
    focusCount: 0,
    scrollCount: 0,
    focus() { this.focusCount += 1; },
    scrollIntoView() { this.scrollCount += 1; }
  };
}

test("cut keyboard maps only native ListView keys and uses physical boundaries", () => {
  const rows = [row(0), row(1), row(2)];
  const helpers = loadCutHelpers(rows);

  assert.equal(helpers.legacyCutKey("ArrowUp"), "arrow-up");
  assert.equal(helpers.legacyCutKey("ArrowDown"), "arrow-down");
  assert.equal(helpers.legacyCutKey("Home"), "home");
  assert.equal(helpers.legacyCutKey("End"), "end");
  assert.equal(helpers.legacyCutKey(" "), "space");
  assert.equal(helpers.legacyCutKey("PageDown"), null);
  assert.equal(helpers.cutKeyboardTarget(rows[0], "ArrowUp").id, 0);
  assert.equal(helpers.cutKeyboardTarget(rows[1], "ArrowDown").id, 2);
  assert.equal(helpers.cutKeyboardTarget(rows[1], "Home").id, 0);
  assert.equal(helpers.cutKeyboardTarget(rows[1], "End").id, 2);
});

test("cut focus is roving and scrolls only for keyboard navigation", () => {
  const rows = [row(0), row(1), row(2)];
  const helpers = loadCutHelpers(rows);

  helpers.focusCutElement(rows[1], true);

  assert.deepEqual(rows.map(item => item.tabIndex), [-1, 0, -1]);
  assert.equal(rows[1].focusCount, 1);
  assert.equal(rows[1].scrollCount, 1);
});

test("cut key intent preserves Home End bubbling and stable PROGRAM selection", () => {
  const start = app.indexOf("function createCutElement");
  const end = app.indexOf("function renderCuts", start);
  const factory = app.slice(start, end);
  assert.match(factory, /element\.addEventListener\("keydown"/);
  assert.match(factory, /event\.preventDefault\(\)/);
  assert.match(factory, /if \(!cutSelectionEnabled\) return/);
  assert.match(factory, /send\("cut-key-down", \{/);
  assert.match(factory, /control: event\.ctrlKey/);
  assert.match(factory, /shift: event\.shiftKey/);
  assert.doesNotMatch(factory, /stopPropagation/);

  assert.match(nativeWindow, /LegacyCutKeyDownIntent key => _controller\.CutKeyDown/);
  assert.doesNotMatch(nativePlayout, /LegacyCutKeyDownIntent or/);
});

test("rendered cut rows expose authoritative focus without replacing DOM rows", () => {
  const start = app.indexOf("function renderCuts");
  const end = app.indexOf("cutList.addEventListener", start);
  const render = app.slice(start, end);
  assert.match(render, /row\.isFocused === true/);
  assert.match(render, /element\.tabIndex/);
  assert.doesNotMatch(render, /replaceChildren/);
});
