import { createHash } from "node:crypto";
import { readFile, readdir } from "node:fs/promises";
import { resolve } from "node:path";

const root = resolve(import.meta.dirname, "..");
const sourcePath = resolve(root, "crates/nana-domain/src/lib.rs");
const hashPath = resolve(root, "contracts/.source.sha256");
const schemaDirectory = resolve(root, "contracts/schema");

const source = await readFile(sourcePath);
const expectedHash = (await readFile(hashPath, "utf8")).trim();
const actualHash = createHash("sha256").update(source).digest("hex");

if (actualHash !== expectedHash) {
  throw new Error(
    "Generated contracts are stale. Install Rust and run `pnpm contracts:generate`."
  );
}

const schemaFiles = (await readdir(schemaDirectory))
  .filter((name) => name.endsWith(".schema.json"))
  .sort();

const required = [
  "app-info.schema.json",
  "character-card.schema.json",
  "demo-pack-summary.schema.json",
  "item-spec.schema.json",
  "persona.schema.json",
  "player-view.schema.json",
  "plot-module.schema.json",
  "resource-bundle.schema.json",
  "resource-header.schema.json",
  "runtime-state.schema.json",
  "story-node.schema.json",
  "turn-failure.schema.json",
  "turn-request.schema.json",
  "turn-result.schema.json",
  "world-book.schema.json"
];

for (const name of required) {
  if (!schemaFiles.includes(name)) {
    throw new Error(`Missing generated schema: contracts/schema/${name}`);
  }
}

for (const name of schemaFiles) {
  const value = JSON.parse(await readFile(resolve(schemaDirectory, name), "utf8"));
  if (typeof value !== "object" || value === null || value.$schema === undefined) {
    throw new Error(`Invalid generated schema: contracts/schema/${name}`);
  }
}

const typeScript = await readFile(resolve(root, "contracts/ts/index.ts"), "utf8");
if (!typeScript.startsWith("// @generated by crates/nana-contracts")) {
  throw new Error("contracts/ts/index.ts is not marked as generated");
}

console.log(`Verified ${schemaFiles.length} schemas and TypeScript DTO source hash.`);
