"use strict";

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

const root = path.resolve(__dirname, "../..");
const app = fs.readFileSync(path.join(root, "Web/app.js"), "utf8");
const index = fs.readFileSync(path.join(root, "Web/index.html"), "utf8");
const styles = fs.readFileSync(path.join(root, "Web/styles.css"), "utf8");
const moduleSource = fs.readFileSync(path.join(root, "Web/market-nav-reorder.js"), "utf8");

test("market reorder module loads before app and binds only to marketNav", () => {
  const moduleIndex = index.indexOf('<script src="market-nav-reorder.js"></script>');
  const appIndex = index.indexOf('<script src="app.js"></script>');
  assert.ok(moduleIndex >= 0 && appIndex > moduleIndex);
  assert.match(app, /const marketNavReorder = globalThis\.MbnMarketNavReorder;/u);
  assert.match(app, /marketNavReorder\.createController\(\{\s*nav: marketNav,/u);
  assert.match(app,
    /isBlocked: \(\) => hasOpenOperatorModal\(\) \|\| isPlaylistSnapshotLocked\(\)/u);
  assert.match(app, /if \(!marketNavReorderController\.mount\(\)\)/u);
});

test("dashboard remains first and exactly ten original data-market identities reorder", () => {
  const nav = index.match(/<nav id="marketNav"[\s\S]*?<\/nav>/u)?.[0] || "";
  const markets = [...nav.matchAll(/data-market="([^"]+)"/gu)].map(match => match[1]);
  assert.deepEqual(markets, [
    "dashboard", "overseas", "exchange", "index", "kospi", "kosdaq",
    "compare", "theme", "foreign-stock", "expert", "halted"
  ]);
  assert.match(moduleSource, /const fixedMarket = "dashboard";/u);
  assert.match(moduleSource, /button\.draggable = reorderable;/u);
  assert.match(moduleSource, /"aria-keyshortcuts", "Alt\+ArrowUp Alt\+ArrowDown"/u);
  assert.match(moduleSource, /"드래그 또는 Alt\+화살표로 업무 탭 순서 변경"/u);
});

test("reorder is DOM/session-only and cannot alter view, DB, or playlist state", () => {
  assert.doesNotMatch(moduleSource,
    /localStorage|sessionStorage|requestMarketData|state\.|playlist|postNative/u);
  assert.match(moduleSource, /nav\.prepend\(dashboard\)/u);
  assert.match(moduleSource, /for \(const market of normalized\) nav\.append/u);

  const clickStart = app.indexOf('marketNav.addEventListener("click"');
  const clickEnd = app.indexOf("elements.catalogSearch.addEventListener", clickStart);
  const clickHandler = app.slice(clickStart, clickEnd);
  assert.match(clickHandler, /state\.activeMarket = button\.dataset\.market;/u);
  assert.doesNotMatch(clickHandler, /children\[|childNodes\[|selectedIndex/u);
  assert.match(clickHandler, /requestMarketData\(state\.activeMarket\)/u);
});

test("drag affordance is visible without changing dashboard markup semantics", () => {
  assert.match(styles, /\.nav-item\[draggable="true"\] \{ cursor: grab; \}/u);
  assert.match(styles, /\.nav-item\.dragging \{ opacity: \.55; cursor: grabbing; \}/u);
});
