/**
 * Client-side release manifest verification + build attestation cache.
 */
import { stableStringify, canonicalBytes } from "./stable_json.js";
import { verify, hexToBytes, bytesToHex, sign } from "./wallet_crypto.js";

/** Filled at build time from release_public.key — placeholder until generate-release-keys.js runs. */
export let RELEASE_PUBLIC_KEY_HEX = "REPLACE_AT_KEYGEN";

export function setReleasePublicKeyHex(hex) {
  RELEASE_PUBLIC_KEY_HEX = String(hex || "").trim();
}

export function verifyReleaseSignature(payloadObj, signatureHex) {
  const pk = hexToBytes(RELEASE_PUBLIC_KEY_HEX);
  const sig = hexToBytes(String(signatureHex || ""));
  if (!pk.length || !sig.length) return false;
  return verify(new Uint8Array(canonicalBytes(payloadObj)), sig, pk);
}

export function verifyReleaseManifest(manifest) {
  if (!manifest || typeof manifest !== "object") return { ok: false, error: "missing manifest" };
  const sig = manifest.signature;
  const body = { ...manifest };
  delete body.signature;
  if (!verifyReleaseSignature(body, sig)) {
    return { ok: false, error: "release manifest signature invalid" };
  }
  return { ok: true, manifest: body };
}

export function pickBuildAttestation(manifest, platform) {
  const p = String(platform || "").toLowerCase();
  const att = manifest && manifest.buildAttestations ? manifest.buildAttestations[p] : "";
  return String(att || "");
}

export function heartbeatPayload(body) {
  return {
    address: body.address,
    publicKey: body.publicKey,
    chainHeight: Number(body.chainHeight || 0),
    tipHash: String(body.tipHash || ""),
    tipTimestamp: Number(body.tipTimestamp || 0),
    producingEnabled: body.producingEnabled !== false,
    clientVersion: String(body.clientVersion || ""),
    platform: String(body.platform || ""),
    timestampMs: Number(body.timestampMs || 0),
    buildAttestation: String(body.buildAttestation || ""),
  };
}

export function signHeartbeatPayload(wallet, body) {
  if (!wallet || !wallet.keyPairs || !wallet.keyPairs[0]) {
    throw new Error("wallet not ready");
  }
  const kp = wallet.keyPairs[wallet.currentAddressIndex || 0];
  const payload = heartbeatPayload(body);
  const data = new Uint8Array(canonicalBytes(payload));
  return bytesToHex(sign(data, kp.privateKey));
}

export { stableStringify, canonicalBytes };
