import { createHash } from "node:crypto";
import { execFileSync } from "node:child_process";
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { arch, platform, release } from "node:os";
import * as NodeServices from "@effect/platform-node/NodeServices";
import * as Effect from "effect/Effect";
import * as Option from "effect/Option";
import { findEasProjectId } from "./src/device/easProjectId.ts";

const [fixtureFile, runDirectory, side] = process.argv.slice(2);
if (!fixtureFile || !runDirectory || !["before", "after"].includes(side)) {
  throw new Error("Usage: node evidence-29466-runtime-driver.ts fixtures.json run-directory before|after");
}
const sha256 = (data: string | Buffer) => createHash("sha256").update(data).digest("hex");
const input = JSON.parse(readFileSync(fixtureFile, "utf8"));
const marker = join(resolve(runDirectory), "F21-config-ran");
const outputRoot = join(resolve(runDirectory), side);
mkdirSync(outputRoot, { recursive: true });
const source = readFileSync(new URL("./src/device/easProjectId.ts", import.meta.url));
const rows = [];
for (const fixture of input.fixtures) {
  const root = mkdtempSync(join(outputRoot, `${fixture.id}-`));
  const files = [];
  for (const [file, raw] of Object.entries(fixture.files)) {
    if (file.split("/").includes("..") || file.startsWith("/")) throw new Error("Invalid fixture path");
    const content = (raw as string).replaceAll("__MARKER_ABSOLUTE_PATH__", marker);
    const target = join(root, file);
    mkdirSync(dirname(target), { recursive: true });
    writeFileSync(target, content);
    files.push({ path: file, sha256: sha256(content) });
  }
  const markerBefore = existsSync(marker);
  const result = await Effect.runPromise(findEasProjectId(root).pipe(Effect.provide(NodeServices.layer)));
  const actual = Option.isSome(result) ? result.value : null;
  const markerAfter = existsSync(marker);
  rows.push({
    id: fixture.id, name: fixture.name, root, files,
    expected: side === "before" ? fixture.expectedBefore : fixture.expectedAfter,
    actual,
    match: actual === (side === "before" ? fixture.expectedBefore : fixture.expectedAfter),
    ...(fixture.id === "F21" ? { marker, markerBefore, markerAfter } : {}),
  });
}
const result = {
  capturedAt: new Date().toISOString(),
  side,
  sha: execFileSync("git", ["rev-parse", "HEAD"], { encoding: "utf8" }).trim(),
  cwd: process.cwd(), node: process.version, platform: platform(), arch: arch(), kernel: release(),
  fixtureFile: resolve(fixtureFile), fixtureSha256: sha256(readFileSync(fixtureFile)),
  scannerSha256: sha256(source),
  testSha256: sha256(readFileSync(new URL("./src/device/easProjectId.test.ts", import.meta.url))),
  rows,
};
console.log(JSON.stringify(result, null, 2));
writeFileSync(join(outputRoot, "results.json"), JSON.stringify(result, null, 2) + "\n");
