import { spawnSync } from "node:child_process";
import { createHash } from "node:crypto";
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { resolve } from "node:path";

import { createReleaseCandidate } from "./lib/release-candidate.mjs";

const runId = process.env.DADA_TDD_RUN_ID ?? `wp7-01-candidate-${new Date().toISOString().replace(/[^0-9]/g, "")}`;
const runDirectory = resolve("artifacts", "tdd", runId);
if (existsSync(runDirectory)) throw new Error(`Evidence run already exists: ${runId}`);
mkdirSync(runDirectory, { recursive: true });

function run(command, args) {
  const startedAt = new Date().toISOString();
  const executable = process.platform === "win32" ? (process.env.ComSpec ?? "cmd.exe") : command;
  const actualArgs = process.platform === "win32" ? ["/d", "/s", "/c", [command, ...args].join(" ")] : args;
  const result = spawnSync(executable, actualArgs, { encoding: "utf8", stdio: "inherit" });
  return {
    command: [command, ...args].join(" "),
    exit_code: result.status ?? 1,
    finished_at: new Date().toISOString(),
    started_at: startedAt,
  };
}

const commands = [
  run("pnpm", ["test:security"]),
  run("pnpm", ["test:package"]),
  run("pnpm", ["validate:tdd-trace"]),
  run("node", ["--test", "tests/package/wp7-01-candidate.test.mjs"]),
];
const failed = commands.filter(({ exit_code }) => exit_code !== 0);
let candidate;
if (failed.length === 0) {
  const commit = spawnSync("git", ["rev-parse", "HEAD"], { encoding: "utf8" }).stdout.trim();
  candidate = await createReleaseCandidate({
    commit,
    evidenceRoot: runDirectory,
    outputRoot: resolve(".build", runId),
  });
}

writeFileSync(resolve(runDirectory, "commands.json"), `${JSON.stringify({ commands, run_id: runId, schema_version: "1.0" }, null, 2)}\n`);
const recordPath = resolve(runDirectory, "release-candidate.json");
const missingEvidence = [
  "release-candidate.json",
  "candidate-package/START-HERE.txt",
  "candidate-package/package-manifest.json",
  "candidate-package/package-scan.json",
  "candidate-package/process-tree.json",
  ...(candidate ? [`candidate-package/${candidate.record.candidate_package.file_name}`] : []),
].filter((path) => !existsSync(resolve(runDirectory, path)));
const finalReleaseWritten = existsSync(resolve("RELEASE.json"));
const status = failed.length === 0 && missingEvidence.length === 0 && !finalReleaseWritten ? "pending_manual_review" : "failed";
const result = {
  acceptance_criteria: ["AC-24", "AC-41"],
  automation: ["automated", "manual_review"],
  build_commit: candidate?.record.build_commit ?? null,
  candidate_status: candidate?.record.status ?? null,
  final_release_written: finalReleaseWritten,
  finished_at: new Date().toISOString(),
  fixed_port: candidate?.record.fixed_port ?? null,
  manifest: {
    path: "tasks.manifest.json",
    sha256: createHash("sha256").update(readFileSync("tasks.manifest.json")).digest("hex").toUpperCase(),
  },
  missing_evidence: missingEvidence,
  release_gate: ["release:P0-A"],
  requirements: ["NFR-01", "NFR-09"],
  run_id: runId,
  schema_version: "1.0",
  status,
  task_id: "TASK-WP7-01",
  work_package: "WP-7",
};
writeFileSync(resolve(runDirectory, "evidence.json"), `${JSON.stringify(result, null, 2)}\n`);
console.log(JSON.stringify(result, null, 2));
if (status === "failed") process.exit(1);
