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

const exactUrl = "https://legacy-parity.mbn.local/index.html";
const requiredSelector = Object.freeze({
  searchText: "삼성전자",
  marketText: "코스피",
  stockName: "삼성전자",
  cutLabel: "1열판기본_현재가",
  graphicType: "1열판기본",
  subtype: "현재가",
  preparedCode: "5001",
  pageNumberOneBased: 1
});
const acceptedArguments = new Set([
  "port", "plan", "plan-sha256", "authorization", "authorization-sha256",
  "output", "screenshot", "capability-sha256", "permit-pipe", "timeout-ms"
]);
const forbiddenCdpMethods = new Set([
  "Browser.close", "Page.close", "Runtime.terminateExecution", "Target.closeTarget"
]);

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

const known = message => { throw new GateFailure("KNOWN_FAILURE", message); };
const unknown = message => { throw new GateFailure("OUTCOME_UNKNOWN", message); };
const sha256 = bytes => createHash("sha256").update(bytes).digest("hex").toUpperCase();
const isSha256 = value => /^[0-9A-F]{64}$/u.test(String(value || ""));
const isSafeId = value => /^[A-Za-z0-9._:-]{1,128}$/u.test(String(value || ""));

function parseArguments(argv) {
  if (argv.length === 0 || argv.length % 2 !== 0) known("Arguments must be --name value pairs.");
  const values = new Map();
  for (let index = 0; index < argv.length; index += 2) {
    const raw = argv[index];
    const value = argv[index + 1];
    if (!raw?.startsWith("--") || !value) known("Every argument requires a value.");
    const name = raw.slice(2);
    if (!acceptedArguments.has(name) || values.has(name)) known(`Invalid argument --${name}.`);
    values.set(name, value);
  }
  for (const name of [
    "port", "plan", "plan-sha256", "authorization", "authorization-sha256",
    "output", "screenshot", "capability-sha256", "permit-pipe"
  ]) {
    if (!values.has(name)) known(`--${name} is required.`);
  }
  const port = Number(values.get("port"));
  if (!Number.isInteger(port) || port < 1 || port > 65535) known("--port is invalid.");
  const timeoutMilliseconds = values.has("timeout-ms") ? Number(values.get("timeout-ms")) : 90000;
  if (!Number.isInteger(timeoutMilliseconds) || timeoutMilliseconds < 15000 ||
      timeoutMilliseconds > 180000) known("--timeout-ms must be 15000 through 180000.");
  const result = {
    port,
    timeoutMilliseconds,
    planPath: path.resolve(values.get("plan")),
    planSha256: String(values.get("plan-sha256")).toUpperCase(),
    authorizationPath: path.resolve(values.get("authorization")),
    authorizationSha256: String(values.get("authorization-sha256")).toUpperCase(),
    outputPath: path.resolve(values.get("output")),
    screenshotPath: path.resolve(values.get("screenshot")),
    capabilitySha256: String(values.get("capability-sha256")).toUpperCase(),
    permitPipeName: String(values.get("permit-pipe"))
  };
  for (const [name, candidate, extension] of [
    ["plan", result.planPath, ".json"],
    ["authorization", result.authorizationPath, ".json"],
    ["output", result.outputPath, ".json"],
    ["screenshot", result.screenshotPath, ".png"]
  ]) {
    if (!path.isAbsolute(values.get(name)) || path.extname(candidate).toLowerCase() !== extension) {
      known(`--${name} must be an absolute ${extension} path.`);
    }
  }
  if (!isSha256(result.planSha256) || !isSha256(result.authorizationSha256) ||
      !isSha256(result.capabilitySha256)) {
    known("A supplied SHA-256 is invalid.");
  }
  if (!/^MBN_STOCK_WEBVIEW\.GateA\.Node\.[0-9A-F]{32}$/u.test(result.permitPipeName)) {
    known("The parent-owned JIT permit pipe name is invalid.");
  }
  if (new Set([result.planPath, result.authorizationPath, result.outputPath, result.screenshotPath]
    .map(value => value.toLowerCase())).size !== 4) known("Evidence paths must be distinct.");
  if (fs.existsSync(result.outputPath) || fs.existsSync(result.screenshotPath)) {
    known("Output evidence is never overwritten.");
  }
  return result;
}

function readFrozenJson(filePath, label, expectedHash = null) {
  const bytes = fs.readFileSync(filePath);
  const actualHash = sha256(bytes);
  if (expectedHash && actualHash !== expectedHash) known(`${label} SHA-256 changed.`);
  let value;
  try { value = JSON.parse(bytes.toString("utf8")); }
  catch { known(`${label} is not strict JSON.`); }
  return { bytes, hash: actualHash, value };
}

const configuration = parseArguments(process.argv.slice(2));
if (Object.keys(process.env).some(name => name.startsWith("MBN_LEGACY_PGM_GATE_A_"))) {
  known("Gate A bearer material must not be inherited through the Node environment.");
}
const startedAtUtc = new Date().toISOString();
const hardDeadline = Date.now() + configuration.timeoutMilliseconds;
const evidence = {
  schemaVersion: 1,
  result: "RUNNING",
  startedAtUtc,
  completedAtUtc: null,
  planSha256: configuration.planSha256,
  roundId: null,
  target: { expectedUrl: exactUrl, port: configuration.port, id: null },
  commandBudget: { connect: 1, prepare: 1, takeIn: 0, next: 0, pageNext: 0, takeOut: 0, databaseWrite: 0, appClose: 0, retry: 0 },
  observed: {
    prepareDispatchPossible: false,
    prepareIssued: false,
    busyObserved: false,
    jitPermitRequested: false,
    jitPermitReceived: false,
    outboundTypes: [],
    blocked: []
  },
  checkpoints: [],
  screenshot: null,
  finalState: null,
  error: null
};

let socket = null;
let nextRpcId = 1;
const pending = new Map();
let prepareDispatchPossible = false;
let prepareIssued = false;

function assertDeadline(label) {
  if (Date.now() >= hardDeadline) unknown(`Global Gate A deadline expired ${label}; no retry.`);
}

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

function validateFrozenContract() {
  const planFile = readFrozenJson(configuration.planPath, "plan", configuration.planSha256);
  const plan = planFile.value;
  if (plan?.schemaVersion !== 1 || plan?.kind !== "LegacyPgmPrepareGatePlan" ||
      !isSafeId(plan.roundId) || plan?.webView?.url !== exactUrl ||
      plan?.webView?.address !== "127.0.0.1" ||
      plan?.webView?.port !== configuration.port ||
      plan?.safety?.nodeHelperInvocationMaximum !== 1 ||
      plan?.safety?.nodeHelperFailStopRequired !== true ||
      plan?.safety?.packageWrapperFailStopRequired !== true ||
      plan?.safety?.forceCloseForbidden !== true ||
      plan?.safety?.automaticSessionCleanupForbiddenAfterLaunch !== true) {
    known("Plan identity or target contract is invalid.");
  }
  const databasePin = plan?.configuration?.database;
  if (typeof databasePin?.path !== "string" || !path.isAbsolute(databasePin.path) ||
      !Number.isSafeInteger(databasePin?.length) || databasePin.length <= 0 ||
      !isSha256(databasePin?.sha256)) {
    known("Plan database configuration pin is invalid.");
  }
  const selectorMap = {
    marketText: requiredSelector.marketText,
    stockName: requiredSelector.stockName,
    cutLabel: requiredSelector.cutLabel,
    graphicType: requiredSelector.graphicType,
    subtype: requiredSelector.subtype,
    sceneAlias: requiredSelector.preparedCode
  };
  for (const [name, value] of Object.entries(selectorMap)) {
    if (plan?.selector?.[name] !== value) known(`Plan selector ${name} is not exact.`);
  }
  if (plan?.selector?.groupCode !== "KOSPI" || plan?.selector?.stockCode !== "005930" ||
      plan?.selector?.normalizedSubtype !== "CURRENT" ||
      plan?.cut?.sceneCode !== "5001" ||
      plan?.cut?.pageNumberOneBased !== requiredSelector.pageNumberOneBased) {
    known("Plan selector identity is incomplete.");
  }
  const limits = plan?.budgets;
  if (limits?.connect !== 1 || limits?.prepare !== 1 || limits?.takeIn !== 0 ||
      limits?.next !== 0 || limits?.pageNext !== 0 || limits?.takeOut !== 0 ||
      limits?.databaseWrite !== 0 || limits?.appClose !== 0 || limits?.retry !== 0) {
    known("Plan command budget is not exact Gate A.");
  }
  const authorizationFile = readFrozenJson(
    configuration.authorizationPath,
    "authorization",
    configuration.authorizationSha256);
  const authorization = authorizationFile.value;
  const approvedAt = Date.parse(authorization?.authorizedAtUtc || "");
  const expiresAt = Date.parse(authorization?.expiresAtUtc || "");
  if (authorization?.schemaVersion !== 1 ||
      authorization?.kind !== "LegacyPgmPrepareGateAuthorization" ||
      authorization?.roundId !== plan.roundId ||
      String(authorization?.planSha256 || "").toUpperCase() !== configuration.planSha256 ||
      authorization?.authorizationStatement !==
        "I_AUTHORIZE_CURRENT_PGM_LIVE_CONNECT_ONCE_AND_PREPARE_5001_PAGE_1_ONCE" ||
      authorization?.currentK3dLicenseValid !== true ||
      authorization?.runningTornadoIsLicensedMainProgram !== true ||
      authorization?.currentPgmApproved !== true ||
      !Number.isFinite(approvedAt) || !Number.isFinite(expiresAt) ||
      expiresAt <= approvedAt || expiresAt - approvedAt > 15 * 60 * 1000 ||
      Date.now() < approvedAt - 5000 || Date.now() >= expiresAt - 5000) {
    known("Gate A authorization is invalid, expired, or too near expiry.");
  }
  const authorizationBudget = authorization?.budgets;
  if (authorizationBudget?.connect !== 1 || authorizationBudget?.prepare !== 1 ||
      authorizationBudget?.takeIn !== 0 || authorizationBudget?.next !== 0 ||
      authorizationBudget?.pageNext !== 0 || authorizationBudget?.takeOut !== 0 ||
      authorizationBudget?.databaseWrite !== 0 || authorizationBudget?.appClose !== 0 ||
      authorizationBudget?.retry !== 0) {
    known("Authorization command budget is not exact Gate A.");
  }
  evidence.roundId = plan.roundId;
  return { plan, authorization, authorizationHash: authorizationFile.hash, expiresAt };
}

async function discoverTarget() {
  let lastError = null;
  while (Date.now() < hardDeadline) {
    try {
      const response = await fetch(`http://127.0.0.1:${configuration.port}/json/list`, {
        redirect: "error", signal: AbortSignal.timeout(1000)
      });
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      const targets = await response.json();
      const exact = Array.isArray(targets) ? targets.filter(target =>
        target?.type === "page" && target.url === exactUrl) : [];
      if (exact.length > 1) known("More than one exact WebView target exists.");
      if (exact.length === 1) return exact[0];
    } catch (error) { lastError = String(error?.message || error); }
    await sleep(100);
  }
  known(`Exact WebView target was not found${lastError ? `: ${lastError}` : "."}`);
}

function validateEndpoint(target) {
  if (!target?.id || !target.webSocketDebuggerUrl) known("Target has no CDP endpoint.");
  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}`) known("CDP endpoint is not exact loopback.");
  evidence.target.id = target.id;
  return endpoint;
}

async function connect(endpoint) {
  if (typeof WebSocket !== "function") known("Node WebSocket API is unavailable.");
  socket = new WebSocket(endpoint.href);
  await new Promise((resolve, reject) => {
    const timer = setTimeout(() => reject(new GateFailure("OUTCOME_UNKNOWN", "CDP open timed out.")), 5000);
    socket.addEventListener("open", () => { clearTimeout(timer); resolve(); }, { once: true });
    socket.addEventListener("error", () => {
      clearTimeout(timer); reject(new GateFailure("OUTCOME_UNKNOWN", "CDP open failed."));
    }, { once: true });
  });
  socket.addEventListener("message", event => {
    let message;
    try { message = JSON.parse(String(event.data)); } catch { return; }
    if (!Object.hasOwn(message, "id")) return;
    const request = pending.get(message.id);
    if (!request) return;
    pending.delete(message.id);
    clearTimeout(request.timer);
    if (message.error) request.reject(new GateFailure("KNOWN_FAILURE", `${request.method}: ${message.error.message}`));
    else request.resolve(message.result);
  });
  socket.addEventListener("close", () => {
    for (const request of pending.values()) {
      clearTimeout(request.timer);
      request.reject(new GateFailure("OUTCOME_UNKNOWN", `${request.method} interrupted by CDP close.`));
    }
    pending.clear();
  });
}

function rpc(method, params = {}, timeoutMilliseconds = 10000) {
  assertDeadline(`before ${method}`);
  if (forbiddenCdpMethods.has(method)) known(`Forbidden CDP method ${method}.`);
  if (!socket || socket.readyState !== WebSocket.OPEN) unknown(`CDP is unavailable for ${method}.`);
  const id = nextRpcId++;
  return new Promise((resolve, reject) => {
    const timer = setTimeout(() => {
      pending.delete(id);
      reject(new GateFailure("OUTCOME_UNKNOWN", `${method} timed out; no retry.`));
    }, Math.min(timeoutMilliseconds, hardDeadline - Date.now()));
    pending.set(id, { method, resolve, reject, timer });
    socket.send(JSON.stringify({ id, method, params }));
  });
}

async function evaluate(expression) {
  const response = await rpc("Runtime.evaluate", {
    expression, awaitPromise: true, returnByValue: true, userGesture: false
  });
  if (response.exceptionDetails) known(response.exceptionDetails.exception?.description ||
    response.exceptionDetails.text || "Runtime evaluation failed.");
  return response.result?.value;
}

async function installGate(planSha256, capabilitySha256) {
  const token = `legacy-pgm-prepare-${Date.now()}`;
  const result = await evaluate(`(() => {
    if (!window.chrome?.webview) throw new Error("WebView bridge unavailable");
    if (globalThis.__legacyPgmPrepareGate) throw new Error("Gate already installed");
    const allowedBeforePrepare = new Set([
      "ready", "search-stocks", "select-stock", "cut-pointer-down", "drop-selected-cuts"
    ]);
    const gate = {
      version: 1,
      token: ${JSON.stringify(token)},
      planSha256: ${JSON.stringify(planSha256)},
      capabilityHash: ${JSON.stringify(capabilitySha256)},
      original: window.chrome.webview.postMessage,
      wrapper: null,
      listener: null,
      states: [],
      outbound: [],
      blocked: [],
      armed: false,
      prepareCapability: null,
      prepareCount: 0,
      prepareIssuedAtUtc: null,
      stateCountAtPrepare: null,
      expectedPreRevision: null,
      busyObservedAtPreRevision: false
    };
    const hashText = async value => {
      const bytes = new TextEncoder().encode(value);
      const digest = await crypto.subtle.digest("SHA-256", bytes);
      return Array.from(new Uint8Array(digest), b => b.toString(16).padStart(2, "0"))
        .join("").toUpperCase();
    };
    gate.listener = event => {
      if (event.data?.type !== "state" || !event.data.payload) return;
      const state = structuredClone(event.data.payload);
      gate.states.push(state);
      if (gate.states.length > 500) gate.states.shift();
      if (gate.prepareCount === 1 && state?.isBusy === true &&
          state?.revision === gate.expectedPreRevision) {
        gate.busyObservedAtPreRevision = true;
      }
    };
    gate.wrapper = message => {
      const type = typeof message?.type === "string" ? message.type : null;
      const payload = message?.payload;
      const record = { type, atUtc: new Date().toISOString() };
      gate.outbound.push(record);
      let allowed = false;
      if (type === "gate-a-prepare") {
        const empty = payload && typeof payload === "object" &&
          !Array.isArray(payload) && Object.keys(payload).length === 1 &&
          typeof payload.capability === "string" &&
          payload.capability === gate.prepareCapability;
        allowed = gate.armed && gate.prepareCount === 0 && empty;
        if (allowed) {
          gate.armed = false;
          gate.prepareCapability = null;
          gate.prepareCount = 1;
          gate.prepareIssuedAtUtc = record.atUtc;
          gate.stateCountAtPrepare = gate.states.length;
        }
      } else {
        allowed = !gate.armed && gate.prepareCount === 0 && allowedBeforePrepare.has(type);
      }
      if (!allowed) {
        if (gate.armed) {
          gate.armed = false;
          gate.prepareCapability = null;
        }
        gate.blocked.push(record);
        return;
      }
      return gate.original.call(window.chrome.webview, message);
    };
    gate.arm = async (supplied, expectedPreRevision) => {
      if (gate.armed || gate.prepareCount !== 0 || gate.blocked.length !== 0 ||
          !Number.isSafeInteger(expectedPreRevision) || expectedPreRevision < 0 ||
          await hashText(String(supplied || "")) !== gate.capabilityHash) {
        throw new Error("One-shot PREPARE capability rejected");
      }
      gate.expectedPreRevision = expectedPreRevision;
      gate.prepareCapability = String(supplied);
      gate.armed = true;
      return { armed: true, stateCount: gate.states.length };
    };
    gate.inspect = () => ({
      version: gate.version,
      token: gate.token,
      planSha256: gate.planSha256,
      wrapperCurrent: window.chrome.webview.postMessage === gate.wrapper,
      stateCount: gate.states.length,
      states: gate.states.slice(),
      outbound: gate.outbound.slice(),
      blocked: gate.blocked.slice(),
      armed: gate.armed,
      prepareCount: gate.prepareCount,
      prepareIssuedAtUtc: gate.prepareIssuedAtUtc,
      stateCountAtPrepare: gate.stateCountAtPrepare,
      expectedPreRevision: gate.expectedPreRevision,
      busyObservedAtPreRevision: gate.busyObservedAtPreRevision
    });
    window.chrome.webview.postMessage = gate.wrapper;
    if (window.chrome.webview.postMessage !== gate.wrapper) throw new Error("Gate identity failed");
    window.chrome.webview.addEventListener("message", gate.listener);
    globalThis.__legacyPgmPrepareGate = Object.freeze({
      arm: gate.arm,
      inspect: gate.inspect
    });
    window.chrome.webview.postMessage({ type: "ready", payload: {} });
    return { token: gate.token, wrapperCurrent: window.chrome.webview.postMessage === gate.wrapper };
  })()`);
  if (result?.token !== token || result.wrapperCurrent !== true) unknown("Page gate did not install exactly.");
}

function projectedState(state) {
  if (!state) return null;
  const playout = state.playout || {};
  return {
    revision: state.revision, isBusy: state.isBusy, statusMessage: state.statusMessage,
    statusKind: state.statusKind,
    playlist: (state.playlist || []).map(row => ({
      rowId: row.rowId, isEnabled: row.isEnabled, isActive: row.isActive,
      marketText: row.marketText, stockName: row.stockName,
      graphicType: row.graphicType, subtype: row.subtype, pageText: row.pageText
    })),
    playout: {
      mode: playout.mode, connectionState: playout.connectionState, phase: playout.phase,
      isConnected: playout.isConnected, isCommandAvailable: playout.isCommandAvailable,
      liveTakeInAllowed: playout.liveTakeInAllowed,
      isPlayCompletionPending: playout.isPlayCompletionPending,
      isTakeOutCompletionPending: playout.isTakeOutCompletionPending,
      outcomeUnknown: playout.outcomeUnknown, preparedCode: playout.preparedCode,
      onAirCode: playout.onAirCode, currentEntryId: playout.currentEntryId,
      pageIndexZeroBased: playout.pageIndexZeroBased, pageCount: playout.pageCount,
      pageSize: playout.pageSize, itemCount: playout.itemCount,
      currentPageItemCount: playout.currentPageItemCount, isLastPage: playout.isLastPage,
      nextKind: playout.nextKind, isBusy: playout.isBusy,
      refreshActive: playout.refreshActive, refreshCompletedCount: playout.refreshCompletedCount,
      refreshMaximumCount: playout.refreshMaximumCount,
      refreshLimitReached: playout.refreshLimitReached, message: playout.message
    }
  };
}

async function snapshot() {
  return await evaluate(`(() => {
    const gate = globalThis.__legacyPgmPrepareGate;
    if (!gate || typeof gate.inspect !== "function") return null;
    const audit = gate.inspect();
    const state = audit.states.at(-1) || null;
    return {
      audit,
      state,
      dom: {
        readyState: document.readyState,
        url: location.href,
        connection: (document.getElementById("playout-connection-state")?.textContent || "").trim(),
        status: (document.getElementById("playout-status")?.textContent || "").trim(),
        dialogHidden: document.getElementById("legacy-dialog")?.hidden === true,
        dialogText: (document.getElementById("legacy-dialog-message")?.textContent || "").trim()
      }
    };
  })()`);
}

function assertCommon(value, label) {
  if (!value?.state?.playout || value.dom?.url !== exactUrl ||
      value.dom.readyState !== "complete" || value.audit?.wrapperCurrent !== true) {
    unknown(`Authoritative state or gate missing at ${label}.`);
  }
  if (value.audit.blocked.length !== 0) unknown(`An unapproved message was blocked at ${label}.`);
  if (value.state.playout.outcomeUnknown === true) unknown(`Native outcome is unknown at ${label}.`);
  if (value.state.playout.onAirCode != null || value.state.playout.phase === "program") {
    unknown(`PROGRAM output was observed at ${label}.`);
  }
  if (value.dom.dialogHidden !== true) known(`Legacy dialog is visible at ${label}: ${value.dom.dialogText}`);
}

async function waitFor(label, predicate, timeoutMilliseconds = null) {
  const deadline = Math.min(hardDeadline, Date.now() + (timeoutMilliseconds || configuration.timeoutMilliseconds));
  let last = null;
  while (Date.now() < deadline) {
    last = await snapshot();
    if (last?.state?.playout) assertCommon(last, label);
    if (predicate(last)) return last;
    await sleep(100);
  }
  unknown(`Timed out waiting for ${label}; no retry. Last=${JSON.stringify(projectedState(last?.state))}`);
}

function isConnectedIdle(value) {
  const p = value?.state?.playout;
  return p?.mode === "live" && p.connectionState === "connected" && p.phase === "idle" &&
    p.isConnected === true && p.isCommandAvailable === true && p.liveTakeInAllowed === false &&
    p.outcomeUnknown !== true && p.preparedCode == null && p.onAirCode == null &&
    p.isBusy !== true && p.isPlayCompletionPending !== true &&
    p.isTakeOutCompletionPending !== true && p.refreshActive !== true &&
    value.state.isBusy !== true;
}

function exactPlaylist(state) {
  const rows = state?.playlist || [];
  return rows.length === 1 && rows[0].isEnabled === true && rows[0].isActive === true &&
    rows[0].marketText === requiredSelector.marketText &&
    rows[0].stockName === requiredSelector.stockName &&
    rows[0].graphicType === requiredSelector.graphicType &&
    rows[0].subtype === requiredSelector.subtype && rows[0].pageText === "1/1";
}

function assertExactOutbound(audit, expectPrepare) {
  const types = audit?.outbound?.map(item => item.type) || [];
  const count = type => types.filter(value => value === type).length;
  const selectedCount = count("select-stock");
  if (count("ready") !== 1 || count("search-stocks") !== 1 ||
      selectedCount > 1 || count("cut-pointer-down") !== 1 ||
      count("drop-selected-cuts") !== 1 ||
      count("gate-a-prepare") !== (expectPrepare ? 1 : 0) ||
      audit?.blocked?.length !== 0 ||
      audit?.prepareCount !== (expectPrepare ? 1 : 0)) {
    unknown("Gate A outbound ledger counts are not exact.");
  }
  const expected = ["ready", "search-stocks"];
  if (selectedCount === 1) expected.push("select-stock");
  expected.push("cut-pointer-down", "drop-selected-cuts");
  if (expectPrepare) expected.push("gate-a-prepare");
  if (types.length !== expected.length ||
      types.some((type, index) => type !== expected[index])) {
    unknown(`Gate A outbound ledger order is not exact: ${JSON.stringify(types)}`);
  }
}

function isPrepared5001(value) {
  const p = value?.state?.playout;
  const row = value?.state?.playlist?.[0];
  return exactPlaylist(value?.state) && p?.mode === "live" &&
    p.connectionState === "connected" && p.phase === "prepared" && p.isConnected === true &&
    p.isCommandAvailable === true && p.liveTakeInAllowed === false && p.outcomeUnknown !== true &&
    p.preparedCode === "5001" && p.onAirCode == null && p.currentEntryId === row?.rowId &&
    p.pageIndexZeroBased === 0 && p.pageCount === 1 && p.itemCount === 1 &&
    p.currentPageItemCount === 1 && p.isLastPage === true &&
    String(p.nextKind).toLowerCase() === "endofplaylist" &&
    p.isBusy !== true && p.isPlayCompletionPending !== true &&
    p.isTakeOutCompletionPending !== true && p.refreshActive !== true &&
    value.state.isBusy !== true;
}

async function click(expression, label) {
  const geometry = await evaluate(`(() => {
    const element = ${expression};
    if (!element || element.disabled || element.getAttribute("aria-disabled") === "true") return null;
    const r = element.getBoundingClientRect();
    if (r.width <= 0 || r.height <= 0) return null;
    return { x: r.left + r.width / 2, y: r.top + r.height / 2 };
  })()`);
  if (!geometry) known(`${label} is unavailable.`);
  await rpc("Input.dispatchMouseEvent", { type: "mouseMoved", ...geometry });
  await rpc("Input.dispatchMouseEvent", {
    type: "mousePressed", ...geometry, button: "left", buttons: 1, clickCount: 1
  });
  await rpc("Input.dispatchMouseEvent", {
    type: "mouseReleased", ...geometry, button: "left", buttons: 0, clickCount: 1
  });
}

async function configurePlaylist() {
  await evaluate(`(() => {
    const input = document.getElementById("stock-search");
    if (!input) throw new Error("stock search unavailable");
    input.value = ${JSON.stringify(requiredSelector.searchText)};
  })()`);
  await click('document.getElementById("stock-search-button")', "stock search button");
  let current = await waitFor("exact stock search", value => {
    const state = value?.state;
    return state?.isBusy === false && state.searchText === requiredSelector.searchText &&
      (state.searchResults || []).filter(row => row.displayName === requiredSelector.stockName).length === 1;
  }, 60000);
  const exact = current.state.searchResults.filter(row => row.displayName === requiredSelector.stockName)[0];
  if (current.state.selectedStockIndex !== exact.index) {
    await click(`document.querySelector('#stock-results button[data-result-index="${exact.index}"]')`,
      "exact stock result");
    current = await waitFor("exact stock selection", value =>
      value?.state?.selectedStockIndex === exact.index && value.state.isBusy === false, 15000);
  }
  const geometry = await evaluate(`(() => {
    const state = globalThis.__legacyPgmPrepareGate.inspect().states.at(-1);
    const cut = (state?.cutRows || []).find(row => row.rawLabel ===
      ${JSON.stringify(requiredSelector.cutLabel)} && row.isSeparator !== true);
    if (!cut) return null;
    const source = document.querySelector('#cut-list .cut-row[data-physical-index="' +
      String(cut.physicalIndex) + '"]');
    const target = document.getElementById("playlist-drop-zone");
    if (!source || !target) return null;
    const a = source.getBoundingClientRect();
    const b = target.getBoundingClientRect();
    return {
      physicalIndex: cut.physicalIndex,
      source: { x: a.left + a.width / 2, y: a.top + a.height / 2 },
      threshold: { x: a.left + a.width / 2 + 20, y: a.top + a.height / 2 + 20 },
      target: { x: b.left + b.width / 2, y: b.top + Math.min(80, b.height / 2) }
    };
  })()`);
  if (!geometry) known("Exact 5001 cut row or drop target is unavailable.");
  await rpc("Input.dispatchMouseEvent", { type: "mouseMoved", ...geometry.source });
  await rpc("Input.dispatchMouseEvent", {
    type: "mousePressed", ...geometry.source, button: "left", buttons: 1, clickCount: 1
  });
  await rpc("Input.dispatchMouseEvent", {
    type: "mouseMoved", ...geometry.threshold, button: "left", buttons: 1
  });
  await rpc("Input.dispatchMouseEvent", {
    type: "mouseMoved", ...geometry.target, button: "left", buttons: 1
  });
  await rpc("Input.dispatchMouseEvent", {
    type: "mouseReleased", ...geometry.target, button: "left", buttons: 0, clickCount: 1
  });
  current = await waitFor("exact 5001 playlist", value =>
    value?.state?.isBusy === false && exactPlaylist(value.state), 30000);
  assertExactOutbound(current.audit, false);
  evidence.checkpoints.push({ name: "playlist-5001", state: projectedState(current.state) });
  return current;
}

async function receiveJitCapability(expiresAt) {
  if (Date.now() >= expiresAt - 5000) known("Authorization is too near expiry before JIT permit.");
  evidence.observed.jitPermitRequested = true;
  const remaining = Math.min(15000, hardDeadline - Date.now(), expiresAt - 5000 - Date.now());
  if (remaining <= 0) known("No safe time remains for the JIT permit.");
  const pipePath = `\\\\.\\pipe\\${configuration.permitPipeName}`;
  const capability = await new Promise((resolve, reject) => {
    let settled = false;
    let total = 0;
    const chunks = [];
    const client = net.createConnection(pipePath);
    const finish = (error, value = null) => {
      if (settled) return;
      settled = true;
      clearTimeout(timer);
      client.destroy();
      if (error) reject(error);
      else resolve(value);
    };
    const timer = setTimeout(() => finish(new GateFailure(
      "KNOWN_FAILURE", "The parent did not grant the one-shot JIT permit.")), remaining);
    client.on("data", chunk => {
      total += chunk.length;
      if (total > 64) {
        finish(new GateFailure("KNOWN_FAILURE", "The JIT permit payload length is invalid."));
        return;
      }
      chunks.push(chunk);
    });
    client.on("end", () => {
      const bytes = Buffer.concat(chunks, total);
      try {
        const value = bytes.toString("ascii");
        if (bytes.length !== 64 || !/^[0-9A-F]{64}$/u.test(value) ||
            sha256(bytes) !== configuration.capabilitySha256) {
          finish(new GateFailure("KNOWN_FAILURE", "The JIT permit did not match the sealed capability hash."));
          return;
        }
        finish(null, value);
      } finally {
        bytes.fill(0);
        for (const chunk of chunks) chunk.fill(0);
      }
    });
    client.on("error", () => finish(new GateFailure(
      "KNOWN_FAILURE", "The parent-owned JIT permit pipe closed without authority.")));
  });
  evidence.observed.jitPermitReceived = true;
  return capability;
}

async function prepareOnce(expiresAt) {
  if (Date.now() >= expiresAt - 5000) known("Authorization is too near expiry before PREPARE.");
  let before = await snapshot();
  assertCommon(before, "PREPARE boundary");
  if (!isConnectedIdle(before) || !exactPlaylist(before.state)) known("PREPARE boundary is not exact IDLE 5001.");
  const preRevision = before.state.revision;
  let capability = await receiveJitCapability(expiresAt);
  before = await snapshot();
  assertCommon(before, "post-permit PREPARE boundary");
  if (before.state.revision !== preRevision || !isConnectedIdle(before) ||
      !exactPlaylist(before.state)) {
    capability = null;
    known("The exact PREPARE boundary changed while the parent granted the JIT permit.");
  }
  const armed = await evaluate(`globalThis.__legacyPgmPrepareGate.arm(
    ${JSON.stringify(capability)}, ${JSON.stringify(preRevision)})`);
  if (armed?.armed !== true) unknown("PREPARE permit did not arm.");
  if (Date.now() >= expiresAt - 5000) known("Authorization expired at PREPARE boundary.");
  prepareDispatchPossible = true;
  evidence.observed.prepareDispatchPossible = true;
  const dispatched = await evaluate(`(() => {
    if (!globalThis.__legacyPgmPrepareGate) throw new Error("PREPARE gate unavailable");
    window.chrome.webview.postMessage({
      type: "gate-a-prepare",
      payload: { capability: ${JSON.stringify(capability)} }
    });
    return true;
  })()`);
  capability = null;
  if (dispatched !== true) unknown("PREPARE bridge dispatch did not return exactly.");
  prepareIssued = true;
  evidence.observed.prepareIssued = true;
  let current;
  let busyObserved = false;
  while (Date.now() < hardDeadline) {
    current = await snapshot();
    assertCommon(current, "PREPARE observation");
    if (current.audit.prepareCount !== 1) unknown("PREPARE one-shot ledger changed.");
    if (current.audit.busyObservedAtPreRevision === true) {
      busyObserved = true;
      evidence.observed.busyObserved = true;
    }
    if (busyObserved && isPrepared5001(current) && current.state.revision > preRevision) {
      evidence.checkpoints.push({ name: "prepared-5001", state: projectedState(current.state) });
      return current;
    }
    const p = current.state.playout;
    if (busyObserved && current.state.isBusy === false && current.state.revision > preRevision &&
        p.phase === "idle" && p.preparedCode == null && p.onAirCode == null &&
        p.outcomeUnknown !== true && String(current.state.statusKind).toLowerCase() === "error" &&
        String(current.state.statusMessage || "").length > 0) {
      throw new GateFailure("KNOWN_FAILURE", `PREPARE rejected: ${current.state.statusMessage}`);
    }
    await sleep(100);
  }
  unknown("PREPARE outcome timed out; no retry or cleanup command was sent.");
}

async function captureScreenshot() {
  const response = await rpc("Page.captureScreenshot", {
    format: "png", fromSurface: true, captureBeyondViewport: false
  }, 15000);
  if (!response?.data) known("Screenshot data is unavailable.");
  const bytes = Buffer.from(response.data, "base64");
  const pngSignature = Buffer.from([0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]);
  if (bytes.length < 1024 || !bytes.subarray(0, pngSignature.length).equals(pngSignature)) {
    unknown("Screenshot is not a nontrivial PNG image.");
  }
  fs.mkdirSync(path.dirname(configuration.screenshotPath), { recursive: true });
  fs.writeFileSync(configuration.screenshotPath, bytes, { flag: "wx" });
  evidence.screenshot = {
    path: configuration.screenshotPath, bytes: bytes.length, sha256: sha256(bytes)
  };
}

async function execute() {
  const contract = validateFrozenContract();
  evidence.authorizationSha256 = contract.authorizationHash;
  const target = await discoverTarget();
  await connect(validateEndpoint(target));
  await rpc("Runtime.enable");
  await rpc("Page.enable");
  await installGate(configuration.planSha256, configuration.capabilitySha256);
  const connected = await waitFor("Live connected IDLE", value => isConnectedIdle(value), 60000);
  if ((connected.state.playlist || []).length !== 0) known("Gate A requires an empty playlist.");
  evidence.checkpoints.push({ name: "connected-idle", state: projectedState(connected.state) });
  await configurePlaylist();
  const prepared = await prepareOnce(contract.expiresAt);
  assertExactOutbound(prepared.audit, true);
  await captureScreenshot();
  const final = await snapshot();
  assertCommon(final, "post-screenshot final verification");
  assertExactOutbound(final.audit, true);
  if (final.audit.busyObservedAtPreRevision !== true || !isPrepared5001(final)) {
    unknown("Post-screenshot state is not the exact prepared 5001 result.");
  }
  evidence.finalState = projectedState(final.state);
  evidence.observed.outboundTypes = final.audit.outbound.map(item => item.type);
  evidence.observed.blocked = final.audit.blocked;
  evidence.result = "PASS_PREPARED";
}

try {
  await execute();
} catch (error) {
  let category = error instanceof GateFailure ? error.category : "HARNESS_ERROR";
  if (socket?.readyState === WebSocket.OPEN) {
    try {
      const final = await snapshot();
      evidence.finalState = projectedState(final?.state);
      evidence.observed.outboundTypes = final?.audit?.outbound?.map(item => item.type) || [];
      evidence.observed.blocked = final?.audit?.blocked || [];
      if (final?.audit?.prepareCount === 1) {
        prepareIssued = true;
        evidence.observed.prepareIssued = true;
      }
      if (!fs.existsSync(configuration.screenshotPath)) await captureScreenshot();
    } catch (captureError) {
      evidence.captureError = String(captureError?.message || captureError);
    }
  }
  const isExactKnownRejection = prepareIssued && category === "KNOWN_FAILURE" &&
    String(error?.message || "").includes("PREPARE rejected:");
  if (prepareDispatchPossible && !isExactKnownRejection) category = "OUTCOME_UNKNOWN";
  evidence.result = category;
  evidence.error = { name: error?.name || "Error", message: String(error?.message || error) };
  process.exitCode = category === "KNOWN_FAILURE" ? 2 : 3;
} finally {
  evidence.completedAtUtc = new Date().toISOString();
  fs.mkdirSync(path.dirname(configuration.outputPath), { recursive: true });
  fs.writeFileSync(configuration.outputPath, JSON.stringify(evidence, null, 2) + "\n", {
    encoding: "utf8", flag: "wx"
  });
  try { socket?.close(); } catch { /* The page and its installed guard stay open. */ }
}
