import fs from "node:fs";
import path from "node:path";
import { createHash, randomBytes } from "node:crypto";

const exactTargetUrl = "https://legacy-parity.mbn.local/index.html";
const allowedOutboundTypes = new Set([
  "ready",
  "select-tab",
  "set-operator-appearance"
]);
const forbiddenCdpMethods = new Set([
  "Browser.close",
  "Page.close",
  "Runtime.terminateExecution",
  "Target.closeTarget",
  "Input.dispatchMouseEvent",
  "Input.dispatchKeyEvent",
  "Input.insertText"
]);
const appearanceValues = Object.freeze({
  colorTheme: Object.freeze(["system", "light", "dark"]),
  viewMode: Object.freeze(["automatic", "compact", "cards"]),
  startWorkspace: Object.freeze(["stockCut", "lastWorkspace"])
});
const controls = Object.freeze({
  settings: Object.freeze({
    id: "workspace-settings-tab",
    expression: 'document.getElementById("workspace-settings-tab")'
  }),
  colorTheme: Object.freeze({
    id: "operator-color-theme",
    expression: 'document.getElementById("operator-color-theme")'
  }),
  viewMode: Object.freeze({
    id: "operator-view-mode",
    expression: 'document.getElementById("operator-view-mode")'
  }),
  startWorkspace: Object.freeze({
    id: "operator-start-workspace",
    expression: 'document.getElementById("operator-start-workspace")'
  })
});

class AppearanceFailure extends Error {
  constructor(category, message) {
    super(`${category}: ${message}`);
    this.name = "AppearanceFailure";
    this.category = category;
  }
}

function failKnown(message) {
  throw new AppearanceFailure("KNOWN_FAILURE", message);
}

function failUnknown(message) {
  throw new AppearanceFailure("OUTCOME_UNKNOWN", message);
}

function parseClosedValue(values, name, allowed) {
  const value = values.get(name);
  if (!allowed.includes(value)) failKnown(`--${name} is outside the closed value set.`);
  return value;
}

function parseArguments(argv) {
  const accepted = new Set([
    "phase",
    "port",
    "output",
    "screenshot",
    "exchange-directory",
    "expected-color-theme",
    "expected-view-mode",
    "expected-start-workspace",
    "final-color-theme",
    "final-view-mode",
    "final-start-workspace",
    "timeout-ms"
  ]);
  if (argv.length === 0 || argv.length % 2 !== 0) {
    failKnown(
      "Usage: node scripts/Test-LegacyPackageAppearanceSmoke.mjs " +
      "--phase mutate|verify-restore --port <port> --output <absolute.json> " +
      "--screenshot <absolute.png> --exchange-directory <absolute-directory> " +
      "--expected-color-theme <value> --expected-view-mode <value> " +
      "--expected-start-workspace <value> --final-color-theme <value> " +
      "--final-view-mode <value> --final-start-workspace <value> " +
      "[--timeout-ms <milliseconds>]");
  }
  const values = new Map();
  for (let index = 0; index < argv.length; index += 2) {
    const rawName = argv[index];
    const value = argv[index + 1];
    if (!rawName?.startsWith("--") || !value) failKnown("Arguments must be --name value pairs.");
    const name = rawName.slice(2);
    if (!accepted.has(name) || values.has(name)) failKnown(`Invalid argument --${name}.`);
    values.set(name, value);
  }
  for (const required of [
    "phase", "port", "output", "screenshot", "exchange-directory",
    "expected-color-theme", "expected-view-mode", "expected-start-workspace",
    "final-color-theme", "final-view-mode", "final-start-workspace"
  ]) {
    if (!values.has(required)) failKnown(`--${required} is required.`);
  }
  const phase = values.get("phase");
  if (!new Set(["mutate", "verify-restore"]).has(phase)) {
    failKnown("--phase must be mutate or verify-restore.");
  }
  const port = Number(values.get("port"));
  const timeoutMilliseconds = Number(values.get("timeout-ms") || "120000");
  if (!Number.isInteger(port) || port < 1024 || port > 65_535) {
    failKnown("--port must be from 1024 through 65535.");
  }
  if (!Number.isInteger(timeoutMilliseconds) ||
      timeoutMilliseconds < 30_000 || timeoutMilliseconds > 900_000) {
    failKnown("--timeout-ms must be from 30000 through 900000.");
  }
  const outputPath = path.resolve(values.get("output"));
  const screenshotPath = path.resolve(values.get("screenshot"));
  const exchangeDirectory = path.resolve(values.get("exchange-directory"));
  if (!path.isAbsolute(values.get("output")) ||
      path.extname(outputPath).toLowerCase() !== ".json" ||
      !path.isAbsolute(values.get("screenshot")) ||
      path.extname(screenshotPath).toLowerCase() !== ".png" ||
      !path.isAbsolute(values.get("exchange-directory"))) {
    failKnown("Output, screenshot and exchange paths must be absolute and typed correctly.");
  }
  if (new Set([
    outputPath.toLowerCase(), screenshotPath.toLowerCase(), exchangeDirectory.toLowerCase()
  ]).size !== 3) {
    failKnown("Evidence paths must be distinct.");
  }
  if (fs.existsSync(outputPath) || fs.existsSync(screenshotPath) ||
      !fs.existsSync(exchangeDirectory) ||
      !fs.statSync(exchangeDirectory).isDirectory() ||
      fs.readdirSync(exchangeDirectory).length !== 0) {
    failKnown("Evidence is never overwritten and the exchange directory must be empty.");
  }
  const expected = Object.freeze({
    colorTheme: parseClosedValue(
      values, "expected-color-theme", appearanceValues.colorTheme),
    viewMode: parseClosedValue(values, "expected-view-mode", appearanceValues.viewMode),
    startWorkspace: parseClosedValue(
      values, "expected-start-workspace", appearanceValues.startWorkspace)
  });
  const final = Object.freeze({
    colorTheme: parseClosedValue(values, "final-color-theme", appearanceValues.colorTheme),
    viewMode: parseClosedValue(values, "final-view-mode", appearanceValues.viewMode),
    startWorkspace: parseClosedValue(
      values, "final-start-workspace", appearanceValues.startWorkspace)
  });
  if (Object.keys(expected).some(key => expected[key] === final[key])) {
    failKnown("Every phase must physically change all three appearance values.");
  }
  return {
    phase,
    port,
    timeoutMilliseconds,
    outputPath,
    screenshotPath,
    exchangeDirectory,
    expected,
    final
  };
}

const configuration = parseArguments(process.argv.slice(2));
const hardDeadline = Date.now() + configuration.timeoutMilliseconds;
let socket = null;
let nextRpcId = 1;
let nextExchangeSequence = 1;
let probeInstalled = false;
let cancellationRequested = false;
const pendingRpc = new Map();
const evidence = {
  schemaVersion: 1,
  profile: "operator-appearance-persistence",
  phase: configuration.phase,
  result: "RUNNING",
  startedAt: new Date().toISOString(),
  completedAt: null,
  target: {
    expectedUrl: exactTargetUrl,
    port: configuration.port,
    id: null,
    url: null
  },
  expectedInitial: configuration.expected,
  expectedFinal: configuration.final,
  safety: {
    requiredMode: "dryRun",
    requiredPhase: "idle",
    inputRetryCount: 0,
    appCloseRequested: false,
    playoutIntentIssued: false,
    allowedOutboundTypes: [...allowedOutboundTypes],
    observedOutboundTypes: [],
    blockedOutboundMessages: [],
    stateViolations: []
  },
  persistenceVerifiedBeforeInput: false,
  startWorkspaceBehaviorVerifiedBeforeInput: false,
  selections: [],
  exchanges: [],
  checkpoints: [],
  finalSnapshot: null,
  screenshot: null,
  error: null
};

process.stdin.setEncoding("utf8");
process.stdin.on("data", chunk => {
  if (String(chunk).split(/\r?\n/u).includes("CANCEL")) cancellationRequested = true;
});
if (typeof process.stdin.unref === "function") process.stdin.unref();

function assertDeadline(label) {
  if (cancellationRequested) failUnknown(`The wrapper cancelled ${label}; no input was retried.`);
  if (Date.now() >= hardDeadline) {
    failUnknown(`The global deadline expired ${label}; no input was retried.`);
  }
}

async function sleep(milliseconds) {
  assertDeadline("before waiting");
  await new Promise(resolve => setTimeout(
    resolve,
    Math.max(0, Math.min(milliseconds, hardDeadline - Date.now()))));
  assertDeadline("after waiting");
}

function sha256(bytes) {
  return createHash("sha256").update(bytes).digest("hex").toUpperCase();
}

function exactAppearance(value) {
  return value ? {
    colorTheme: value.colorTheme,
    viewMode: value.viewMode,
    startWorkspace: value.startWorkspace
  } : null;
}

function appearanceEquals(left, right) {
  return Boolean(left && right &&
    left.colorTheme === right.colorTheme &&
    left.viewMode === right.viewMode &&
    left.startWorkspace === right.startWorkspace);
}

async function discoverTarget() {
  const discoveryUrl = `http://127.0.0.1:${configuration.port}/json/list`;
  const deadline = Math.min(hardDeadline, Date.now() + 15_000);
  while (Date.now() < deadline) {
    try {
      const response = await fetch(discoveryUrl, { cache: "no-store" });
      if (response.ok) {
        const targets = await response.json();
        const exact = targets.filter(target =>
          target?.type === "page" && target.url === exactTargetUrl);
        if (exact.length > 1) failKnown("More than one exact package WebView target exists.");
        if (exact.length === 1) return exact[0];
      }
    } catch (error) {
      if (error instanceof AppearanceFailure) throw error;
    }
    await sleep(100);
  }
  failKnown("The exact package target was not found.");
}

function validateEndpoint(target) {
  if (!target?.id || !target.webSocketDebuggerUrl) failKnown("The target has no debugger URL.");
  const endpoint = new URL(target.webSocketDebuggerUrl);
  if (endpoint.protocol !== "ws:" || endpoint.hostname !== "127.0.0.1" ||
      Number(endpoint.port) !== configuration.port ||
      endpoint.pathname !== `/devtools/page/${target.id}`) {
    failKnown("The debugger endpoint is not the exact loopback page endpoint.");
  }
  return endpoint;
}

async function connect(endpoint) {
  if (typeof WebSocket !== "function") failKnown("This Node runtime has no WebSocket API.");
  socket = new WebSocket(endpoint.href);
  await new Promise((resolve, reject) => {
    const timer = setTimeout(() => reject(new AppearanceFailure(
      "OUTCOME_UNKNOWN", "CDP socket open timed out.")), 5_000);
    socket.addEventListener("open", () => { clearTimeout(timer); resolve(); }, { once: true });
    socket.addEventListener("error", () => { clearTimeout(timer); reject(new AppearanceFailure(
      "OUTCOME_UNKNOWN", "CDP socket failed to open.")); }, { once: true });
  });
  socket.addEventListener("message", event => {
    const message = JSON.parse(String(event.data));
    if (!Object.hasOwn(message, "id")) return;
    const pending = pendingRpc.get(message.id);
    if (!pending) return;
    pendingRpc.delete(message.id);
    clearTimeout(pending.timer);
    if (message.error) pending.reject(new AppearanceFailure(
      "KNOWN_FAILURE", `${pending.method} failed: ${message.error.message || "CDP error"}`));
    else pending.resolve(message.result);
  });
}

async function rpc(method, params = {}, timeoutMilliseconds = 10_000) {
  assertDeadline(`before ${method}`);
  if (forbiddenCdpMethods.has(method)) failKnown(`CDP method ${method} is forbidden.`);
  if (!socket || socket.readyState !== WebSocket.OPEN) failUnknown("CDP socket is not open.");
  const id = nextRpcId++;
  return await new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      pendingRpc.delete(id);
      reject(new AppearanceFailure(
        "OUTCOME_UNKNOWN", `${method} timed out; no input was retried.`));
    }, Math.min(timeoutMilliseconds, Math.max(1, hardDeadline - Date.now())));
    pendingRpc.set(id, { resolve, reject, timer, method });
    socket.send(JSON.stringify({ id, method, params }));
  });
}

async function evaluate(expression) {
  const result = await rpc("Runtime.evaluate", {
    expression,
    awaitPromise: true,
    returnByValue: true
  });
  if (result?.exceptionDetails) failKnown("A read-only page inspection failed.");
  return result?.result?.value;
}

async function installProbe() {
  const token = `appearance-${Date.now()}-${randomBytes(8).toString("hex")}`;
  const installed = await evaluate(`(() => {
    if (!window.chrome?.webview) throw new Error("WebView2 bridge is unavailable.");
    if (globalThis.__legacyAppearanceProbe) throw new Error("Appearance probe already exists.");
    const probe = {
      token: ${JSON.stringify(token)},
      states: [],
      outboundMessages: [],
      blockedOutboundMessages: [],
      stateViolations: [],
      inputEvents: [],
      originalPostMessage: window.chrome.webview.postMessage,
      postMessageWrapper: null,
      stateListener: null,
      inputListener: null
    };
    const allowed = new Set(${JSON.stringify([...allowedOutboundTypes])});
    probe.stateListener = event => {
      if (event.data?.type !== "state" || !event.data.payload) return;
      const state = event.data.payload;
      probe.states.push(structuredClone(state));
      if (probe.states.length > 100) probe.states.shift();
      const playout = state.playout;
      const reasons = [];
      if (!playout) reasons.push("missing-playout");
      else {
        if (playout.mode !== "dryRun") reasons.push("mode");
        if (playout.phase !== "idle") reasons.push("phase");
        if (playout.isConnected === true) reasons.push("connected");
        if (playout.preparedCode != null) reasons.push("prepared-code");
        if (playout.onAirCode != null) reasons.push("on-air-code");
        if (playout.outcomeUnknown === true) reasons.push("outcome-unknown");
        if (playout.isPlayCompletionPending === true) reasons.push("play-pending");
        if (playout.isTakeOutCompletionPending === true) reasons.push("takeout-pending");
        if (playout.isBusy === true) reasons.push("playout-busy");
        if (playout.refreshActive === true) reasons.push("refresh-active");
      }
      if (reasons.length > 0) probe.stateViolations.push({
        at: new Date().toISOString(),
        revision: state.revision ?? null,
        reasons
      });
    };
    probe.inputListener = event => {
      const element = event.target instanceof Element ? event.target : null;
      const controlled = element?.closest?.(
        "#workspace-settings-tab, #operator-color-theme, " +
        "#operator-view-mode, #operator-start-workspace");
      if (!controlled) return;
      probe.inputEvents.push({
        sequence: probe.inputEvents.length + 1,
        type: event.type,
        targetId: controlled.id || null,
        isTrusted: event.isTrusted === true,
        pointerType: event.pointerType || null,
        button: Number.isInteger(event.button) ? event.button : null,
        buttons: Number.isInteger(event.buttons) ? event.buttons : null,
        key: typeof event.key === "string" ? event.key : null,
        value: controlled instanceof HTMLSelectElement ? controlled.value : null,
        at: new Date().toISOString()
      });
      if (probe.inputEvents.length > 150) probe.inputEvents.shift();
    };
    probe.postMessageWrapper = message => {
      const type = typeof message?.type === "string" ? message.type : null;
      const record = {
        sequence: probe.outboundMessages.length + 1,
        type,
        appearance: type === "set-operator-appearance" ? {
          colorTheme: message?.payload?.colorTheme ?? null,
          viewMode: message?.payload?.viewMode ?? null,
          startWorkspace: message?.payload?.startWorkspace ?? null
        } : null,
        at: new Date().toISOString()
      };
      probe.outboundMessages.push(record);
      if (!type || !allowed.has(type)) {
        probe.blockedOutboundMessages.push(record);
        return;
      }
      return probe.originalPostMessage.call(window.chrome.webview, message);
    };
    try {
      window.chrome.webview.postMessage = probe.postMessageWrapper;
      if (window.chrome.webview.postMessage !== probe.postMessageWrapper) {
        throw new Error("The outbound safety gate could not be installed.");
      }
      globalThis.__legacyAppearanceProbe = probe;
      window.chrome.webview.addEventListener("message", probe.stateListener);
      ["pointerdown", "pointerup", "keydown", "keyup", "input", "change"].forEach(type =>
        document.addEventListener(type, probe.inputListener, true));
      window.chrome.webview.postMessage({ type: "ready", payload: {} });
    } catch (error) {
      window.chrome.webview.postMessage = probe.originalPostMessage;
      delete globalThis.__legacyAppearanceProbe;
      throw error;
    }
    return probe.token;
  })()`);
  if (installed !== token) failKnown("The safety probe was not installed exactly once.");
  probeInstalled = true;
}

async function removeProbe() {
  if (!probeInstalled || !socket || socket.readyState !== WebSocket.OPEN) return;
  const removed = await evaluate(`(() => {
    const probe = globalThis.__legacyAppearanceProbe;
    if (!probe) return false;
    window.chrome.webview.removeEventListener("message", probe.stateListener);
    ["pointerdown", "pointerup", "keydown", "keyup", "input", "change"].forEach(type =>
      document.removeEventListener(type, probe.inputListener, true));
    if (window.chrome.webview.postMessage !== probe.postMessageWrapper) {
      throw new Error("The outbound safety gate identity changed.");
    }
    window.chrome.webview.postMessage = probe.originalPostMessage;
    delete globalThis.__legacyAppearanceProbe;
    return true;
  })()`);
  if (removed !== true) failUnknown("The safety probe was not restored exactly once.");
  probeInstalled = false;
}

async function readSnapshot() {
  return await evaluate(`(() => {
    const probe = globalThis.__legacyAppearanceProbe;
    const state = probe?.states?.at(-1) || null;
    const html = document.documentElement;
    const body = document.body;
    const active = document.activeElement;
    const appearance = state?.operatorSettings ? {
      colorTheme: state.operatorSettings.colorTheme,
      viewMode: state.operatorSettings.viewMode,
      startWorkspace: state.operatorSettings.startWorkspace
    } : null;
    return {
      state: state ? {
        revision: state.revision,
        isBusy: state.isBusy === true,
        playout: structuredClone(state.playout),
        operatorSettings: state.operatorSettings ? {
          revision: state.operatorSettings.revision,
          colorTheme: state.operatorSettings.colorTheme,
          viewMode: state.operatorSettings.viewMode,
          startWorkspace: state.operatorSettings.startWorkspace,
          restartRequired: state.operatorSettings.restartRequired === true,
          message: state.operatorSettings.message || "",
          messageKind: state.operatorSettings.messageKind || null
        } : null
      } : null,
      appearance,
      safety: {
        wrapped: probe?.postMessageWrapper != null &&
          window.chrome?.webview?.postMessage === probe.postMessageWrapper,
        outboundMessages: (probe?.outboundMessages || []).map(value => ({ ...value })),
        blockedOutboundMessages: (probe?.blockedOutboundMessages || []).map(value => ({ ...value })),
        stateViolations: (probe?.stateViolations || []).map(value => ({
          ...value,
          reasons: [...value.reasons]
        })),
        inputEvents: (probe?.inputEvents || []).map(value => ({ ...value }))
      },
      dom: {
        url: location.href,
        readyState: document.readyState,
        bodyBusy: body.getAttribute("aria-busy"),
        connectionText: (document.getElementById("playout-connection-state")?.textContent || "").trim(),
        settingsVisible: document.getElementById("settings-workspace")?.hidden === false &&
          document.getElementById("settings-workspace")?.inert !== true,
        settingsCurrent: document.getElementById("workspace-settings-tab")
          ?.getAttribute("aria-current") || null,
        activeWorkspace: document.getElementById("workspace-region")
          ?.dataset?.activeWorkspace || null,
        activeElementId: active?.id || null,
        selects: {
          colorTheme: document.getElementById("operator-color-theme")?.value ?? null,
          viewMode: document.getElementById("operator-view-mode")?.value ?? null,
          startWorkspace: document.getElementById("operator-start-workspace")?.value ?? null
        },
        htmlAppearance: {
          colorTheme: html.dataset.colorTheme || null,
          viewMode: html.dataset.viewMode || null,
          startWorkspace: html.dataset.startWorkspace || null
        },
        bodyAppearance: {
          colorTheme: body.dataset.colorTheme || null,
          viewMode: body.dataset.viewMode || null,
          startWorkspace: body.dataset.startWorkspace || null
        },
        computed: {
          colorScheme: getComputedStyle(html).colorScheme || null,
          bodyBackground: getComputedStyle(body).backgroundColor || null
        },
        legacyDialogHidden: document.getElementById("legacy-dialog")?.hidden === true,
        namedModalHidden: document.getElementById("named-playlist-modal")?.hidden === true,
        namedConfirmationHidden:
          document.getElementById("named-playlist-confirmation")?.hidden === true
      }
    };
  })()`);
}

function updateSafety(snapshot) {
  evidence.safety.observedOutboundTypes =
    snapshot?.safety?.outboundMessages?.map(row => row.type) || [];
  evidence.safety.blockedOutboundMessages =
    snapshot?.safety?.blockedOutboundMessages || [];
  evidence.safety.stateViolations = snapshot?.safety?.stateViolations || [];
  evidence.safety.playoutIntentIssued = evidence.safety.observedOutboundTypes.some(type =>
    ["prepare-playout", "take-in", "next-playout", "take-out",
      "choose-background", "toggle-background"].includes(type));
}

function assertSafety(snapshot, label, allowBusy = false) {
  updateSafety(snapshot);
  if (!snapshot?.state?.playout || snapshot.safety.wrapped !== true) {
    failUnknown(`The native DryRun state or safety gate is missing at ${label}.`);
  }
  if (snapshot.safety.blockedOutboundMessages.length > 0) {
    failKnown(`An unapproved outbound message was blocked at ${label}.`);
  }
  if (snapshot.safety.stateViolations.length > 0) {
    failUnknown(`DryRun left its safe state at ${label}.`);
  }
  const playout = snapshot.state.playout;
  if (playout.mode !== "dryRun" || playout.phase !== "idle" ||
      playout.isConnected === true || playout.preparedCode != null ||
      playout.onAirCode != null || playout.outcomeUnknown === true ||
      playout.isPlayCompletionPending === true ||
      playout.isTakeOutCompletionPending === true || playout.isBusy === true ||
      playout.refreshActive === true) {
    failUnknown(`Playout is not exact DryRun IDLE at ${label}.`);
  }
  if (!allowBusy && snapshot.state.isBusy === true) {
    failKnown(`The operator UI is busy at ${label}.`);
  }
  if (snapshot.dom.url !== exactTargetUrl || snapshot.dom.readyState !== "complete" ||
      snapshot.dom.connectionText !== "DRY RUN" ||
      snapshot.dom.legacyDialogHidden !== true ||
      snapshot.dom.namedModalHidden !== true ||
      snapshot.dom.namedConfirmationHidden !== true) {
    failKnown(`The exact package document is not ready at ${label}.`);
  }
}

async function waitFor(label, predicate, { allowBusy = false, allowMissingState = false } = {}) {
  if (allowMissingState && label !== "DryRun IDLE preflight") {
    failKnown("Only the input-free initial preflight may await the first native state.");
  }
  const deadline = Math.min(hardDeadline, Date.now() + 45_000);
  let last = null;
  while (Date.now() < deadline) {
    last = await readSnapshot();
    if (!last?.state?.playout && allowMissingState) {
      if (last?.safety?.wrapped !== true || last?.dom?.url !== exactTargetUrl ||
          last?.dom?.readyState !== "complete" || last?.dom?.connectionText !== "DRY RUN") {
        failUnknown("The exact DryRun document changed before the first state.");
      }
      updateSafety(last);
      if (evidence.safety.blockedOutboundMessages.length > 0 ||
          evidence.safety.stateViolations.length > 0) {
        failUnknown("The safety gate observed a violation before initial state.");
      }
      await sleep(100);
      continue;
    }
    assertSafety(last, label, allowBusy);
    if (predicate(last)) return last;
    await sleep(100);
  }
  failUnknown(`Timed out waiting for ${label}; no input was retried.`);
}

function assertAppearanceSnapshot(snapshot, expected, label, requireNeutralLoad = false) {
  if (!appearanceEquals(snapshot.appearance, expected) ||
      !appearanceEquals(snapshot.dom.selects, expected) ||
      !appearanceEquals(snapshot.dom.htmlAppearance, expected) ||
      !appearanceEquals(snapshot.dom.bodyAppearance, expected) ||
      snapshot.state.operatorSettings?.restartRequired !== false) {
    failKnown(`The native and rendered appearance do not agree at ${label}.`);
  }
  if (requireNeutralLoad && new Set(["warning", "error"])
      .has(snapshot.state.operatorSettings?.messageKind)) {
    failKnown("The existing operator settings could not be loaded cleanly before input.");
  }
}

async function geometryFor(control) {
  const value = await evaluate(`(() => {
    const element = ${control.expression};
    if (!element) return null;
    element.scrollIntoView({ block: "nearest", inline: "nearest" });
    const rect = element.getBoundingClientRect();
    return {
      x: rect.left + rect.width / 2,
      y: rect.top + rect.height / 2,
      width: rect.width,
      height: rect.height,
      viewport: {
        width: document.documentElement.clientWidth,
        height: document.documentElement.clientHeight
      },
      devicePixelRatio: window.devicePixelRatio,
      disabled: element.disabled === true,
      hidden: element.hidden === true || element.closest("[hidden]") != null,
      optionValues: element instanceof HTMLSelectElement
        ? [...element.options].map(option => option.value) : null
    };
  })()`);
  if (!value || value.disabled || value.hidden || value.width <= 0 || value.height <= 0 ||
      !Number.isFinite(value.x) || !Number.isFinite(value.y) ||
      value.x < 0 || value.y < 0 ||
      value.x >= value.viewport.width || value.y >= value.viewport.height ||
      value.devicePixelRatio < 0.25 || value.devicePixelRatio > 5) {
    failKnown(`#${control.id} is not a unique visible physical-input target.`);
  }
  return value;
}

function exchangePath(sequence, suffix) {
  return path.join(configuration.exchangeDirectory,
    `${String(sequence).padStart(2, "0")}.${suffix}.json`);
}

function readSmallJson(filePath, label) {
  const stat = fs.statSync(filePath);
  if (!stat.isFile() || stat.size <= 0 || stat.size > 64 * 1024) {
    failKnown(`${label} is empty or too large.`);
  }
  const bytes = fs.readFileSync(filePath);
  let value;
  try { value = JSON.parse(bytes.toString("utf8")); }
  catch { failKnown(`${label} is not strict JSON.`); }
  return { value, bytes, sha256: sha256(bytes) };
}

async function waitForTrustedInput(control, startIndex, targetValue) {
  const deadline = Math.min(hardDeadline, Date.now() + 10_000);
  while (Date.now() < deadline) {
    const events = await evaluate(`(() =>
      (globalThis.__legacyAppearanceProbe?.inputEvents || [])
        .slice(${Number(startIndex)}).map(value => ({ ...value })))()`);
    const relevant = events.filter(event => event.targetId === control.id);
    const down = relevant.find(event => event.type === "pointerdown");
    const up = relevant.find(event => event.type === "pointerup");
    if (down && up) {
      if (down.sequence >= up.sequence || down.isTrusted !== true || up.isTrusted !== true ||
          down.pointerType !== "mouse" || up.pointerType !== "mouse" ||
          down.button !== 0 || up.button !== 0 || down.buttons !== 1 || up.buttons !== 0) {
        failKnown(`#${control.id} did not receive one trusted mouse down/up pair.`);
      }
      if (targetValue === null) return { pointerDown: down, pointerUp: up, change: null };
      const change = relevant.find(event =>
        event.type === "change" && event.isTrusted === true && event.value === targetValue);
      const trustedKeyDowns = relevant.filter(event =>
        event.type === "keydown" && event.isTrusted === true);
      // A native HTML <select> popup consumes Home/ArrowDown/Enter before the
      // page can observe DOM keydown events. The wrapper's sealed one-shot ack
      // proves those physical key counts; the page proves the trusted change.
      if (change) {
        return {
          pointerDown: down,
          pointerUp: up,
          change,
          observedTrustedKeyDownCount: trustedKeyDowns.length,
          observedKeys: trustedKeyDowns.map(event => event.key)
        };
      }
    }
    await sleep(25);
  }
  failUnknown(`#${control.id} trusted input evidence did not appear; no input was retried.`);
}

async function requestPhysicalInput({
  operation,
  control,
  appearanceKey = null,
  targetValue = null,
  expectedBefore,
  expectedAfter
}) {
  const sequence = nextExchangeSequence++;
  const token = randomBytes(16).toString("hex").toUpperCase();
  const geometry = await geometryFor(control);
  let optionIndex = null;
  if (appearanceKey) {
    if (!Array.isArray(geometry.optionValues) ||
        JSON.stringify(geometry.optionValues) !==
          JSON.stringify(appearanceValues[appearanceKey])) {
      failKnown(`#${control.id} option order is outside the closed contract.`);
    }
    optionIndex = geometry.optionValues.indexOf(targetValue);
    if (optionIndex < 0) failKnown(`#${control.id} lacks the requested option.`);
  }
  const eventStart = await evaluate(
    "globalThis.__legacyAppearanceProbe?.inputEvents?.length ?? null");
  const outboundStart = await evaluate(
    "globalThis.__legacyAppearanceProbe?.outboundMessages?.length ?? null");
  if (!Number.isInteger(eventStart) || !Number.isInteger(outboundStart)) {
    failUnknown("The trusted input/outbound evidence baseline is unavailable.");
  }
  const request = {
    schemaVersion: 1,
    phase: configuration.phase,
    sequence,
    token,
    targetUrl: exactTargetUrl,
    operation,
    targetId: control.id,
    appearanceKey,
    targetValue,
    optionIndex,
    expectedBefore,
    expectedAfter,
    point: { x: geometry.x, y: geometry.y },
    viewport: geometry.viewport,
    devicePixelRatio: geometry.devicePixelRatio,
    mouseDownCalls: 1,
    mouseUpCalls: 1,
    homeKeyCalls: appearanceKey ? 1 : 0,
    arrowDownKeyCalls: appearanceKey ? optionIndex : 0,
    enterKeyCalls: appearanceKey ? 1 : 0,
    inputRetryCount: 0
  };
  const requestPath = exchangePath(sequence, "request");
  const acknowledgementPath = exchangePath(sequence, "ack");
  const requestBytes = Buffer.from(`${JSON.stringify(request)}\n`, "utf8");
  fs.writeFileSync(requestPath, requestBytes, { flag: "wx" });
  const deadline = Math.min(hardDeadline, Date.now() + 45_000);
  while (!fs.existsSync(acknowledgementPath)) {
    if (Date.now() >= deadline) {
      failUnknown(`Physical input exchange ${sequence} timed out; no input was retried.`);
    }
    await sleep(50);
  }
  const acknowledgement = readSmallJson(
    acknowledgementPath,
    `Physical input acknowledgement ${sequence}`);
  const ack = acknowledgement.value;
  if (!ack || ack.schemaVersion !== 1 || ack.phase !== configuration.phase ||
      ack.sequence !== sequence || ack.token !== token || ack.result !== "PASS" ||
      ack.operation !== operation || ack.targetId !== control.id ||
      ack.appearanceKey !== appearanceKey || ack.targetValue !== targetValue ||
      ack.optionIndex !== optionIndex || ack.packageIdentityValidated !== true ||
      ack.dryRunValidated !== true || ack.tornadoConnectionCount !== 0 ||
      ack.inputRetryCount !== 0 || ack.mouseDownCalls !== 1 || ack.mouseUpCalls !== 1 ||
      ack.homeKeyCalls !== request.homeKeyCalls ||
      ack.arrowDownKeyCalls !== request.arrowDownKeyCalls ||
      ack.enterKeyCalls !== request.enterKeyCalls ||
      !appearanceEquals(ack.settings?.appearance, expectedAfter)) {
    failKnown(`Physical input acknowledgement ${sequence} is outside its one-shot contract.`);
  }
  const physicalInput = await waitForTrustedInput(
    control,
    eventStart,
    targetValue);
  if (appearanceKey) {
    const current = await waitFor(`#${control.id} native save`, snapshot =>
      appearanceEquals(snapshot.appearance, expectedAfter) &&
      appearanceEquals(snapshot.dom.selects, expectedAfter) &&
      appearanceEquals(snapshot.dom.htmlAppearance, expectedAfter) &&
      appearanceEquals(snapshot.dom.bodyAppearance, expectedAfter) &&
      snapshot.state.isBusy !== true,
    { allowBusy: true });
    const outbound = current.safety.outboundMessages.slice(outboundStart);
    if (outbound.length !== 1 || outbound[0].type !== "set-operator-appearance" ||
        !appearanceEquals(outbound[0].appearance, expectedAfter)) {
      failKnown(`#${control.id} did not issue exactly one closed appearance intent.`);
    }
    evidence.selections.push({
      appearanceKey,
      targetValue,
      expectedAfter,
      trustedChange: true,
      physicalKeyCounts: {
        home: ack.homeKeyCalls,
        arrowDown: ack.arrowDownKeyCalls,
        enter: ack.enterKeyCalls,
        total: ack.homeKeyCalls + ack.arrowDownKeyCalls + ack.enterKeyCalls
      },
      observedDomKeyDownCount: physicalInput.observedTrustedKeyDownCount,
      outboundIntentCount: 1,
      nativeRevision: current.state.operatorSettings.revision,
      restartRequired: current.state.operatorSettings.restartRequired
    });
  }
  evidence.exchanges.push({
    sequence,
    operation,
    targetId: control.id,
    appearanceKey,
    targetValue,
    optionIndex,
    requestPath,
    requestSha256: sha256(requestBytes),
    acknowledgementPath,
    acknowledgementSha256: acknowledgement.sha256,
    physicalKeyCounts: {
      home: ack.homeKeyCalls,
      arrowDown: ack.arrowDownKeyCalls,
      enter: ack.enterKeyCalls
    },
    physicalInput,
    settings: ack.settings
  });
}

async function checkpoint(name, details = null) {
  const snapshot = await readSnapshot();
  assertSafety(snapshot, name, false);
  evidence.checkpoints.push({ name, details, snapshot });
  return snapshot;
}

async function captureScreenshot() {
  const response = await rpc("Page.captureScreenshot", {
    format: "png",
    fromSurface: true,
    captureBeyondViewport: false
  }, 20_000);
  if (!response?.data) failKnown("CDP did not return screenshot data.");
  const bytes = Buffer.from(response.data, "base64");
  fs.writeFileSync(configuration.screenshotPath, bytes, { flag: "wx" });
  evidence.screenshot = {
    path: configuration.screenshotPath,
    bytes: bytes.length,
    sha256: sha256(bytes)
  };
}

async function runSequence() {
  await rpc("Runtime.enable");
  await rpc("Page.enable");
  await installProbe();
  let current = await waitFor("DryRun IDLE preflight", snapshot =>
    snapshot.state?.playout?.mode === "dryRun" &&
    snapshot.state.isBusy !== true &&
    snapshot.state.operatorSettings != null,
  { allowMissingState: true });
  assertAppearanceSnapshot(
    current,
    configuration.expected,
    "input-free initial appearance",
    true);
  evidence.persistenceVerifiedBeforeInput = configuration.phase === "verify-restore";
  if (configuration.phase === "verify-restore") {
    const expectedStartupWorkspace = configuration.expected.startWorkspace === "lastWorkspace"
      ? "settings"
      : "stock";
    current = await waitFor("persisted start workspace behavior", snapshot =>
      appearanceEquals(snapshot.appearance, configuration.expected) &&
      snapshot.dom.activeWorkspace === expectedStartupWorkspace,
    { allowBusy: false });
    evidence.startWorkspaceBehaviorVerifiedBeforeInput = true;
  }
  evidence.checkpoints.push({
    name: configuration.phase === "verify-restore"
      ? "persisted-appearance-after-relaunch"
      : "baseline-appearance-before-mutation",
    expectedStartupWorkspace: configuration.phase === "verify-restore"
      ? (configuration.expected.startWorkspace === "lastWorkspace" ? "settings" : "stock")
      : null,
    snapshot: current
  });

  await requestPhysicalInput({
    operation: "application-click",
    control: controls.settings,
    expectedBefore: configuration.expected,
    expectedAfter: configuration.expected
  });
  current = await waitFor("settings workspace", snapshot =>
    snapshot.dom.settingsVisible === true &&
    snapshot.dom.settingsCurrent === "page" &&
    snapshot.dom.activeWorkspace === "settings",
  { allowBusy: false });
  assertAppearanceSnapshot(current, configuration.expected, "settings workspace preflight");

  let before = configuration.expected;
  for (const appearanceKey of ["colorTheme", "viewMode", "startWorkspace"]) {
    const after = Object.freeze({
      ...before,
      [appearanceKey]: configuration.final[appearanceKey]
    });
    await requestPhysicalInput({
      operation: "select-appearance-option",
      control: controls[appearanceKey],
      appearanceKey,
      targetValue: configuration.final[appearanceKey],
      expectedBefore: before,
      expectedAfter: after
    });
    before = after;
  }

  current = await checkpoint(
    configuration.phase === "verify-restore"
      ? "baseline-restored-by-physical-input"
      : "alternate-appearance-persisted",
    { appearance: configuration.final });
  assertAppearanceSnapshot(current, configuration.final, "final appearance");
  if (evidence.exchanges.length !== 4 || evidence.selections.length !== 3 ||
      nextExchangeSequence !== 5 ||
      evidence.selections.some(selection => selection.trustedChange !== true ||
        selection.physicalKeyCounts.home !== 1 ||
        selection.physicalKeyCounts.enter !== 1 ||
        selection.physicalKeyCounts.total !==
          2 + selection.physicalKeyCounts.arrowDown ||
        selection.outboundIntentCount !== 1 || selection.restartRequired !== false)) {
    failKnown("The closed four-step appearance input plan did not complete exactly once.");
  }
  await captureScreenshot();
  evidence.finalSnapshot = current;
  evidence.result = "PASS";
  evidence.completedAt = new Date().toISOString();
}

async function writeEvidence() {
  const bytes = Buffer.from(`${JSON.stringify(evidence, null, 2)}\n`, "utf8");
  fs.writeFileSync(configuration.outputPath, bytes, { flag: "wx" });
}

async function main() {
  let exitCode = 0;
  try {
    const target = await discoverTarget();
    evidence.target.id = target.id;
    evidence.target.url = target.url;
    await connect(validateEndpoint(target));
    await runSequence();
  } catch (error) {
    exitCode = 1;
    evidence.result = "FAIL";
    evidence.completedAt = new Date().toISOString();
    evidence.error = {
      category: error instanceof AppearanceFailure ? error.category : "OUTCOME_UNKNOWN",
      message: error instanceof AppearanceFailure
        ? error.message
        : "OUTCOME_UNKNOWN: Unexpected appearance harness failure."
    };
  } finally {
    try {
      await removeProbe();
    } catch (cleanupError) {
      exitCode = 1;
      evidence.result = "FAIL";
      evidence.completedAt = new Date().toISOString();
      evidence.error = {
        category: "OUTCOME_UNKNOWN",
        message: cleanupError instanceof Error
          ? cleanupError.message
          : "OUTCOME_UNKNOWN: Appearance probe cleanup failed."
      };
    }
    if (socket && socket.readyState === WebSocket.OPEN) socket.close();
    if (!fs.existsSync(configuration.outputPath)) {
      try { await writeEvidence(); }
      catch { exitCode = 1; }
    }
  }
  process.exitCode = exitCode;
}

await main();
