import { cpSync, existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { join } from "node:path";
import { generateApplicationTypesWithPlugins } from "../packages/cli/src/types.ts";

const root = process.cwd();
const source = join(root, "examples", "basic-app");
const scratchParent = join(root, ".wrnexus-type-check");
const scratch = mkdtempSync(`${scratchParent}-`);
const generated = [
  join("app", "types", "wrnexus.generated.d.ts"),
  join("app", "types", "wrnexus.plugins.generated.d.ts"),
];

try {
  cpSync(source, scratch, {
    recursive: true,
    filter(path) {
      const relative = path.slice(source.length).replaceAll("\\", "/");
      return !/(?:^|\/)(?:dist|node_modules|\.wrnexus(?:-[^/]*)?)(?:\/|$)/.test(relative);
    },
  });
  await generateApplicationTypesWithPlugins(scratch);

  const stale = generated.filter((relative) => {
    const committed = join(source, relative);
    const expected = join(scratch, relative);
    return (
      !existsSync(committed) ||
      !existsSync(expected) ||
      readFileSync(committed, "utf8") !== readFileSync(expected, "utf8")
    );
  });
  if (stale.length) {
    throw new Error(
      `Generated application types are stale: ${stale.join(", ")}. Run \`bun run generate:example-types\`.`,
    );
  }
  console.log(`Generated application types match ${generated.length} committed artifacts.`);
} finally {
  rmSync(scratch, { recursive: true, force: true });
}
