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 { validateTddTrace } from "./lib/tdd-trace.mjs";
import { buildWp706PrefreezeReport, REQUIRED_UPSTREAM } from "./lib/wp7-06-prefreeze.mjs";

const runId = process.env.DADA_TDD_RUN_ID ?? `wp7-06-prefreeze-${new Date().toISOString().replace(/[^0-9]/g, "")}`;
const runDirectory = resolve("artifacts", "tdd", runId);
const caseDirectory = resolve(runDirectory, "cases", "TDD-WP7-AC-001-trace-structure");
if (existsSync(runDirectory)) throw new Error(`Evidence run already exists: ${runId}`);
mkdirSync(caseDirectory, { recursive: true });

function writeJson(path, value) {
  writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
}

function git(args) {
  const result = spawnSync("git", args, { encoding: "utf8", timeout: 60_000 });
  if ((result.status ?? 1) !== 0) throw new Error(`WP7_06_GIT_COMMAND_FAILED:${args[0]}`);
  return result.stdout.trim();
}

function runCommand(name, command) {
  const startedAt = new Date().toISOString();
  const result = spawnSync(process.env.ComSpec ?? "cmd.exe", ["/d", "/s", "/c", command], {
    encoding: "utf8",
    env: process.env,
    maxBuffer: 64 * 1024 * 1024,
  });
  if (result.stdout) process.stdout.write(result.stdout);
  if (result.stderr) process.stderr.write(result.stderr);
  return {
    command,
    exit_code: result.status ?? 1,
    finished_at: new Date().toISOString(),
    name,
    started_at: startedAt,
  };
}

const commands = [
  runCommand("prefreeze-unit", "node --test tests/package/wp7-06-prefreeze.test.mjs"),
  runCommand("tdd-trace", "pnpm validate:tdd-trace"),
];
if (commands.some((command) => command.exit_code !== 0)) {
  writeJson(resolve(caseDirectory, "commands.json"), { commands, run_id: runId, schema_version: "1.0" });
  process.exit(1);
}

const trace = validateTddTrace();
const currentCommit = git(["rev-parse", "HEAD"]);
const remoteLines = git(["ls-remote", "--heads", "origin", "codex/wp7-01", "codex/wp7-02", "codex/wp7-03", "codex/wp7-04", "codex/wp7-05"])
  .split(/\r?\n/)
  .filter(Boolean);
const remoteHeads = Object.fromEntries(remoteLines.map((line) => {
  const [head, reference] = line.split(/\s+/);
  return [reference.replace("refs/heads/", ""), head];
}));
const upstream = Object.fromEntries(Object.entries(REQUIRED_UPSTREAM).map(([taskId, status]) => {
  const branch = taskId.replace("TASK-", "codex/").toLowerCase();
  const head = remoteHeads[branch];
  const ancestry = spawnSync("git", ["merge-base", "--is-ancestor", head ?? "missing", "HEAD"], { encoding: "utf8", timeout: 30_000 });
  return [taskId, { branch, head, merged: ancestry.status === 0, status }];
}));
const report = buildWp706PrefreezeReport({
  currentCommit,
  releaseExists: existsSync(resolve("RELEASE.json")),
  trace,
  upstream,
});

const result = {
  acceptance_criteria: Array.from({ length: 56 }, (_, index) => index + 1)
    .filter((number) => ![8, 26, 37, 54].includes(number))
    .map((number) => `AC-${String(number).padStart(2, "0")}`),
  automation: ["automated", "manual_review"],
  commit: currentCommit,
  evidence_refs: ["commands.json", "trace-summary.json", "upstream-lineage.json", "deferred-external.json"],
  finished_at: new Date().toISOString(),
  manifest: {
    path: "tasks.manifest.json",
    sha256: createHash("sha256").update(readFileSync("tasks.manifest.json")).digest("hex").toUpperCase(),
  },
  missing_evidence: [],
  release_gate: ["release:P0-A"],
  requirements: ["NFR-05"],
  run_id: runId,
  schema_version: "1.0",
  status: report.status,
  task_id: "TASK-WP7-06",
  test_id: "TDD-WP7-AC-001-trace-structure",
  work_package: "WP-7",
};

writeJson(resolve(caseDirectory, "commands.json"), { commands, run_id: runId, schema_version: "1.0" });
writeJson(resolve(caseDirectory, "trace-summary.json"), { status: trace.status, summary: trace.summary, schema_version: "1.0" });
writeJson(resolve(caseDirectory, "upstream-lineage.json"), { current_commit: currentCommit, tasks: report.upstream, schema_version: "1.0" });
writeJson(resolve(caseDirectory, "deferred-external.json"), {
  policy: "product_owner_first_version_nonblocking",
  tasks: report.deferred_external_tasks,
  treated_as_real_provider_pass: false,
  schema_version: "1.0",
});
writeJson(resolve(caseDirectory, "result.json"), result);
writeJson(resolve(runDirectory, "evidence.json"), { cases: [{ missing_evidence: [], status: result.status, test_id: result.test_id }], run_id: runId, status: result.status, schema_version: "1.0" });
console.log(JSON.stringify({ deferred_external_tasks: report.deferred_external_tasks, next_task: report.next_task, run_id: runId, status: report.status }, null, 2));
