import { execFileSync } from "node:child_process";
import { access, chmod, mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
import { createHash } from "node:crypto";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { REPOSITORY_NAME as name } from "../lib/site-config.ts";
import { sourceFiles, sourceDigest } from "./source-files.mjs";
const root = fileURLToPath(new URL("..", import.meta.url));
const staging = await mkdtemp(join(tmpdir(), "amm-source-"));
const source = join(staging, name), bundle = join(root, "public", `${name}.bundle`);
const exists = async path => access(path).then(() => true, () => false);
const git = args => execFileSync("git", args, { cwd: source, maxBuffer: 20 * 1024 * 1024 });
try {
  const oldBundle = join(root, "public/robinhood-correlated-pairs.bundle");
  const previous = await exists(bundle) ? bundle : await exists(oldBundle) ? oldBundle : null;
  if (previous) execFileSync("git", ["clone", previous, source], { stdio: "ignore" });
  else { await mkdir(source); git(["init", "-b", "main"]); }
  for (const entry of await readdir(source)) if (entry !== ".git") await rm(join(source, entry), { recursive: true, force: true });
  git(["config", "user.name", "AMM Correlated Pairs"]); git(["config", "user.email", "opensource@localhost.invalid"]);
  const files = await sourceFiles(root), digest = sourceDigest(files);
  const release = process.argv.slice(2).join(" ") || "Synchronize current site source";
  const version = { sourceDigest: digest, publishedAt: new Date().toISOString(), release };
  for (const [path, { content, mode }] of files) { await mkdir(dirname(join(source, path)), { recursive: true }); await writeFile(join(source, path), content); await chmod(join(source, path), mode); }
  await writeFile(join(source, "lib/source-manifest.json"), '{"head":"","packPath":"","commits":[],"sourceDigest":"","publishedAt":"","release":""}\n');
  await writeFile(join(source, ".source-version.json"), JSON.stringify(version, null, 2) + "\n");
  await writeFile(join(root, ".source-version.json"), JSON.stringify(version, null, 2) + "\n");
  git(["add", "-A"]); git(["commit", "--allow-empty", "-m", release]);
  const head = git(["rev-parse", "HEAD"]).toString().trim();
  const commits = git(["rev-list", "--all"]).toString().trim().split("\n");
  const pack = git(["pack-objects", "--all", "--stdout"]);
  const packPath = `/git-assets/${createHash("sha256").update(pack).digest("hex").slice(0, 24)}.pack`;
  const manifest = { head, packPath, commits, ...version };
  await mkdir(join(root, "public/git-assets"), { recursive: true });
  await writeFile(join(root, "public", packPath), pack);
  await writeFile(join(root, "lib/source-manifest.json"), JSON.stringify(manifest) + "\n");
  await writeFile(join(root, "public/source.json"), JSON.stringify(manifest, null, 2) + "\n");
  await rm(bundle, { force: true }); git(["bundle", "create", bundle, "--all"]);
  git(["archive", "--format=tar.gz", `--prefix=${name}/`, `--output=${join(root, "public", `${name}.tar.gz`)}`, "HEAD"]);
  if (oldBundle !== bundle) await rm(oldBundle, { force: true });
  await rm(join(root, "public/robinhood-correlated-pairs.tar.gz"), { force: true });
  console.log(`Synced ${name}: ${head}; ${files.size} source files; SHA-256 ${digest}`);
} finally { await rm(staging, { recursive: true, force: true }); }
