import { once } from "node:events";
// Proof script: verifies readResponseWithLimit stops Telegram Bot API response reads at the cap.
import { createServer } from "node:http";
import { resolve } from "node:path";

const pkgRoot = resolve(import.meta.dirname, "..");

const { readResponseWithLimit } = await import(`${pkgRoot}/src/infra/http-body.ts`).catch(
  () => import("openclaw/plugin-sdk/response-limit-runtime"),
);

const CAP = 1 * 1024 * 1024; // 1 MiB proof cap
const STREAM_SIZE = 24 * 1024 * 1024; // 24 MiB – simulates hostile oversized Bot API response

let allPassed = true;
function check(label, val) {
  console.log(`  ${val ? "ok" : "FAIL"}: ${label}`);
  if (!val) {
    allPassed = false;
  }
}

// Server-side byte counter: track how many response bytes were actually written to the socket.
let serverBytesWritten = 0;

async function withServer(fn) {
  serverBytesWritten = 0;
  const server = createServer((req, res) => {
    if (req.url === "/huge") {
      res.writeHead(200, { "Content-Type": "application/json" });
      const chunk = Buffer.alloc(65536, 120); // 64 KiB of 'x'
      const header = Buffer.from('{"ok":true,"result":[');
      res.write(header);
      serverBytesWritten += header.length;

      let sent = header.length;
      const writeNext = () => {
        if (sent >= STREAM_SIZE) {
          const tail = Buffer.from("]}");
          res.write(tail);
          serverBytesWritten += tail.length;
          res.end();
          return;
        }
        const ok = res.write(chunk);
        serverBytesWritten += chunk.length;
        sent += chunk.length;
        if (ok) {
          setImmediate(writeNext);
        } else {
          res.once("drain", writeNext);
        }
      };
      writeNext();
    } else {
      const body = JSON.stringify({
        ok: true,
        result: {
          id: 123456789,
          is_bot: true,
          username: "my_test_bot",
          first_name: "TestBot",
        },
      });
      res.writeHead(200, {
        "Content-Type": "application/json",
        "Content-Length": String(Buffer.byteLength(body)),
      });
      res.end(body);
      serverBytesWritten += Buffer.byteLength(body);
    }
  });
  server.listen(0, "127.0.0.1");
  await once(server, "listening");
  const { port } = server.address();
  try {
    await fn(port, server);
  } finally {
    await new Promise((resolveDone) => {
      server.close(resolveDone);
    });
  }
}

console.log(`\n[proof] Telegram Bot API response-limit`);
console.log(`  cap=${CAP} bytes (1 MiB), would-stream≈${STREAM_SIZE} bytes (24 MiB)\n`);

// ── Case 1: readResponseWithLimit rejects oversized body ─────────────────────
await withServer(async (port) => {
  serverBytesWritten = 0;
  const res = await fetch(`http://127.0.0.1:${port}/huge`);
  let err;
  try {
    await readResponseWithLimit(res, CAP);
  } catch (e) {
    err = e;
  }
  // Give server a tick to flush its internal counter before checking
  await new Promise((done) => {
    setTimeout(done, 50);
  });
  const sent = serverBytesWritten;
  check(`oversized body rejected (threw=${err != null})`, err != null);
  check(
    `error message contains limit info: "${err?.message?.slice(0, 80)}"`,
    err?.message?.includes("limit") === true,
  );
  check(
    `server wrote ≈${sent} bytes, well below 24 MiB (stream was cancelled early)`,
    sent < STREAM_SIZE * 0.1,
  );
});

// ── Negative control: unbounded .json() reads the FULL 24 MiB ────────────────
await withServer(async (port) => {
  serverBytesWritten = 0;
  const res2 = await fetch(`http://127.0.0.1:${port}/huge`);
  await res2.json().catch(() => undefined);
  await new Promise((done) => {
    setTimeout(done, 50);
  });
  const sent2 = serverBytesWritten;
  check(
    `negative control: unbounded .json() caused server to write ≈${sent2} bytes (>> ${CAP})`,
    sent2 > CAP,
  );
});

// ── Case 3: small happy-path response (like real getMe / getUpdates OK) ───────
await withServer(async (port) => {
  const res3 = await fetch(`http://127.0.0.1:${port}/small`);
  const buf = await readResponseWithLimit(res3, CAP);
  const parsed = JSON.parse(buf.toString("utf8"));
  check(
    `small response parsed correctly (ok=${parsed?.ok} id=${parsed?.result?.id})`,
    parsed?.ok === true && parsed?.result?.id === 123456789,
  );
  check(`result bytes within cap (${buf.length} < ${CAP})`, buf.length > 0 && buf.length < CAP);
});

console.log(allPassed ? "\nALL PROOF ASSERTIONS PASSED" : "\nSOME ASSERTIONS FAILED");
process.exit(allPassed ? 0 : 1);
