import console from "node:console";
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
import { runBenchmark, assertBenchmarkBudget } from "../packages/benchmark/src/index.ts";
import { TagCache } from "../packages/cache/src/memory.ts";
import { secureJsonStringify } from "../packages/security/src/serialization.ts";
import { parse } from "../packages/syntax/src/index.ts";

const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const writeReport = process.argv.includes("--write");
const frameworkVersion = JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version;
const componentSource = readFileSync(
  join(root, "packages", "ui", "components", "button.wrn"),
  "utf8",
);
const hydrationPayload = {
  route: "/benchmark",
  user: { id: "user-1", displayName: "WRNexus", token: "must-redact" },
  items: Array.from({ length: 100 }, (_, index) => ({ id: index, label: `Item ${index}` })),
};
const cache = new TagCache({ maxEntries: 1000 });
for (let index = 0; index < 500; index++) cache.set(`item:${index}`, index, { tags: ["items"] });

const benchmarks = [
  {
    result: await runBenchmark("syntax-parse-component", () => parse(componentSource), {
      iterations: 100,
      warmup: 10,
    }),
    budget: { maxAbsoluteMs: 50, minOperationsPerSecond: 20 },
  },
  {
    result: await runBenchmark(
      "secure-hydration-serialization",
      () => secureJsonStringify(hydrationPayload),
      { iterations: 250, warmup: 20 },
    ),
    budget: { maxAbsoluteMs: 20, minOperationsPerSecond: 100 },
  },
  {
    result: await runBenchmark(
      "tag-cache-read-100",
      () => {
        for (let index = 0; index < 100; index++) cache.get(`item:${index}`);
      },
      { iterations: 250, warmup: 20 },
    ),
    budget: { maxAbsoluteMs: 20, minOperationsPerSecond: 100 },
  },
];

for (const benchmark of benchmarks) {
  assertBenchmarkBudget(benchmark.result, undefined, benchmark.budget);
}

const report = {
  schemaVersion: 1,
  frameworkVersion,
  environment: { runtime: process.version, platform: process.platform, arch: process.arch },
  benchmarks: benchmarks.map(({ result, budget }) => ({ result, budget })),
};
if (writeReport) {
  const reportDir = join(root, ".wrnexus", "reports");
  mkdirSync(reportDir, { recursive: true });
  writeFileSync(
    join(reportDir, `benchmark-${frameworkVersion}.json`),
    `${JSON.stringify(report, null, 2)}\n`,
  );
}
console.log(
  JSON.stringify(
    report.benchmarks.map(({ result }) => ({
      name: result.name,
      meanMs: result.meanMs,
      p95Ms: result.p95Ms,
      operationsPerSecond: result.operationsPerSecond,
    })),
    null,
    2,
  ),
);
