"use strict";

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

const repositoryRoot = path.resolve(__dirname, "..", "..");
const webRoot = path.join(repositoryRoot, "src",
  "MBN_STOCK_WEBVIEW.LegacyParityApp", "Web");
const markup = fs.readFileSync(path.join(webRoot, "index.html"), "utf8");
const app = fs.readFileSync(path.join(webRoot, "app.js"), "utf8");
const styles = fs.readFileSync(path.join(webRoot, "styles.css"), "utf8");
const modalFocus = fs.readFileSync(path.join(webRoot, "legacy-modal-focus.js"), "utf8");
const inputSmoke = fs.readFileSync(path.join(
  repositoryRoot, "scripts", "Test-LegacyPackageInput.mjs"), "utf8");

function section(source, startMarker, endMarker) {
  const start = source.indexOf(startMarker);
  assert.notEqual(start, -1, "missing start marker: " + startMarker);
  const end = source.indexOf(endMarker, start + startMarker.length);
  assert.ok(end > start, "missing end marker: " + endMarker);
  return source.slice(start, end);
}

function navButton(tabId) {
  const match = markup.match(new RegExp(
    `<button[^>]*data-tab-id="${tabId}"[\\s\\S]*?<\\/button>`));
  assert.ok(match, "missing navigation button: " + tabId);
  return match[0];
}

test("GraphE and FSell or VI expose the original visible exit controls", () => {
  assert.match(markup,
    /id="manual-financial-workspace"[\s\S]*?<footer class="manual-dialog-footer">\s*<button id="manual-financial-exit" type="button">나가기<\/button>/u);
  assert.match(markup,
    /id="manual-list-workspace"[\s\S]*?<footer class="manual-dialog-footer">\s*<button id="manual-list-cancel" type="button">취소<\/button>/u);
  assert.match(styles,
    /\.manual-financial-dialog\s*\{[^}]*grid-template-rows:\s*46px minmax\(0, 1fr\) auto/u);
  assert.match(styles,
    /\.manual-list-dialog\s*\{[^}]*grid-template-rows:\s*46px minmax\(0, 1fr\) auto/u);
  assert.match(styles, /\.manual-dialog-footer\s*\{[^}]*justify-content:\s*flex-end/u);
});

test("visible text controls reuse the exact top-close actions", () => {
  const financialClose = section(
    app, "function closeManualFinancial", "manualListButtons.forEach");
  assert.equal((financialClose.match(/send\("close-manual-financial"/g) || []).length, 1);
  assert.match(financialClose,
    /manualClose\.addEventListener\("click", closeManualFinancial\)/);
  assert.match(financialClose,
    /manualExit\.addEventListener\("click", closeManualFinancial\)/);

  const listClose = section(
    app, "function closeManualList", "manualWorkspace.addEventListener");
  assert.equal((listClose.match(/send\("close-manual-list"/g) || []).length, 1);
  assert.match(listClose,
    /manualListClose\.addEventListener\("click", closeManualList\)/);
  assert.match(listClose,
    /manualListCancel\.addEventListener\("click", closeManualList\)/);
});

test("text and top-close controls share locking and modal keyboard focus", () => {
  assert.match(app, /manualExit\.disabled = manualClose\.disabled/);
  assert.match(app, /manualListCancel\.disabled = manualListClose\.disabled/);
  assert.match(app,
    /setTransientControlsBusy\(manualDialog, state\.isBusy === true\)/);
  assert.match(app, /setTransientControlsBusy\(manualListDialog, busy\)/);
  assert.match(app,
    /root\.querySelectorAll\("button, input, select, textarea"\)/);
  assert.match(modalFocus,
    /const focusableSelector = \[[\s\S]*?"button"[\s\S]*?\]\.join\(","\)/);

  for (const id of ["manual-financial-exit", "manual-list-cancel"]) {
    const button = markup.match(new RegExp(`<button id="${id}"[^>]*>`));
    assert.ok(button, "missing visible close button: " + id);
    assert.match(button[0], /type="button"/);
    assert.doesNotMatch(button[0], /(?:disabled|tabindex="-1")/);
  }
});

test("full UI input validation physically clicks the restored text controls", () => {
  assert.match(inputSmoke,
    /async function closeManualFinancial[\s\S]*?pointerClick\('document\.getElementById\("manual-financial-exit"\)'/);
  assert.match(inputSmoke,
    /async function closeManualList[\s\S]*?pointerClick\('document\.getElementById\("manual-list-cancel"\)'/);
});

test("clearer sidebar names keep the existing protocol tab IDs", () => {
  const overseas = navButton("overseasStocks");
  assert.match(overseas, /aria-label="해외시장"/u);
  assert.match(overseas, /title="해외시장"/u);
  assert.match(overseas, /<span class="workspace-nav-label">해외시장<\/span>/u);

  const halt = navButton("tradingHalt");
  assert.match(halt, /aria-label="거래정지"/u);
  assert.match(halt, /title="거래정지"/u);
  assert.match(halt, /<span class="workspace-nav-label">거래정지<\/span>/u);
});
