import { describe, it, expect } from "vitest";
import { mkdtempSync, cpSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { execSync } from "node:child_process";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { computeSnapshot } from "../lib/snapshot.js";
import expectedSnapshot from "../__snapshots__/core-package/audit.snapshot.json" with { type: "json" };

// Repo root is 2 levels up from turbo/generators/__tests__
const REPO_ROOT = resolve(fileURLToPath(import.meta.url), "..", "..", "..", "..");

/**
 * Strip "@repo/core-audit" from a package.json file in the tmp tree.
 * Required when simulating a fresh scaffold: core-audit does not exist yet
 * but the snapshot was captured before removal. Apps in the current tree
 * may still list it as a dependency.
 */
function stripCoreAuditDep(pkgJsonPath: string): void {
  const raw = readFileSync(pkgJsonPath, "utf8");
  const parsed = JSON.parse(raw) as Record<string, Record<string, string>>;
  for (const section of ["dependencies", "devDependencies", "peerDependencies"] as const) {
    if (parsed[section]?.["@repo/core-audit"]) {
      delete parsed[section]["@repo/core-audit"];
    }
  }
  writeFileSync(pkgJsonPath, JSON.stringify(parsed, null, 2) + "\n");
}

describe("e2e: core-package audit", () => {
  it("byte-identical reconstruction matches snapshot", { timeout: 120_000 }, () => {
    const tmp = mkdtempSync(join(tmpdir(), "e2e-audit-"));
    cpSync(REPO_ROOT, tmp, {
      recursive: true,
      filter: (src) =>
        !src.includes("node_modules") &&
        !src.includes(".turbo") &&
        !src.includes("packages/core-audit"),
    });

    // Strip @repo/core-audit from apps/web-next/package.json so pnpm install
    // succeeds without the package being present (simulating the post-removal state).
    stripCoreAuditDep(join(tmp, "apps", "web-next", "package.json"));

    execSync(`cd ${tmp} && pnpm install --frozen-lockfile=false`, { stdio: "ignore" });
    execSync(`cd ${tmp} && pnpm turbo gen core-package --args audit`, { stdio: "ignore" });
    const result = computeSnapshot(join(tmp, "packages/core-audit"));
    expect(result).toEqual(expectedSnapshot);
  });
});
