import console from "node:console";
import {
  existsSync,
  mkdirSync,
  mkdtempSync,
  readFileSync,
  readdirSync,
  rmSync,
  writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join, resolve } from "node:path";
import { spawnSync } from "node:child_process";
import process from "node:process";

const root = resolve(import.meta.dirname, "..");
const stageRoot = join(root, ".publish");
const bun = process.env.WRNEXUS_BUN_BINARY || "bun";
const npmCli = join(dirname(process.execPath), "node_modules", "npm", "bin", "npm-cli.js");
if (!existsSync(npmCli)) throw new Error(`Unable to locate the npm CLI at ${npmCli}.`);
const integrityPath = join(stageRoot, "PACKAGE-INTEGRITY.json");
if (!existsSync(integrityPath)) {
  throw new Error("No staged packages found. Run the package staging command first.");
}
const integrity = JSON.parse(readFileSync(integrityPath, "utf8"));
const expectedPackageNames = new Set(
  (Array.isArray(integrity.packages) ? integrity.packages : []).map((entry) => entry.name),
);

const packages = readdirSync(stageRoot, { withFileTypes: true })
  .filter((entry) => entry.isDirectory() && existsSync(join(stageRoot, entry.name, "package.json")))
  .map((entry) => ({
    directory: entry.name,
    manifest: JSON.parse(readFileSync(join(stageRoot, entry.name, "package.json"), "utf8")),
  }))
  .sort((left, right) => left.manifest.name.localeCompare(right.manifest.name));

const stagedPackageNames = new Set(packages.map((pkg) => pkg.manifest.name));
const missingPackages = [...expectedPackageNames].filter((name) => !stagedPackageNames.has(name));
const unexpectedPackages = [...stagedPackageNames].filter(
  (name) => !expectedPackageNames.has(name),
);
if (
  expectedPackageNames.size === 0 ||
  packages.length !== expectedPackageNames.size ||
  missingPackages.length > 0 ||
  unexpectedPackages.length > 0
) {
  throw new Error(
    `Staged package set does not match PACKAGE-INTEGRITY.json (expected ${expectedPackageNames.size}, received ${packages.length}, missing: ${missingPackages.join(", ") || "none"}, unexpected: ${unexpectedPackages.join(", ") || "none"}).`,
  );
}

const consumer = mkdtempSync(join(tmpdir(), "wrnexus-staged-consumer-"));
try {
  const tarballRoot = join(consumer, "tarballs");
  mkdirSync(tarballRoot, { recursive: true });
  const dependencies = {};
  for (const pkg of packages) {
    const packed = spawnSync(
      process.execPath,
      [npmCli, "pack", join(stageRoot, pkg.directory), "--pack-destination", tarballRoot, "--json"],
      { cwd: consumer, encoding: "utf8" },
    );
    if (packed.status !== 0) {
      throw new Error(
        `Unable to pack ${pkg.manifest.name}:\n${packed.error?.message || packed.stderr || packed.stdout || `exit ${packed.status}`}`,
      );
    }
    const result = JSON.parse(packed.stdout);
    const filename = result[0]?.filename;
    if (typeof filename !== "string") {
      throw new Error(`npm pack returned no tarball for ${pkg.manifest.name}.`);
    }
    dependencies[pkg.manifest.name] = `file:${join(tarballRoot, filename).replace(/\\/g, "/")}`;
  }
  writeFileSync(
    join(consumer, "package.json"),
    JSON.stringify(
      { name: "wrnexus-staged-consumer", private: true, type: "module", dependencies },
      null,
      2,
    ) + "\n",
  );
  const install = spawnSync(
    process.execPath,
    [npmCli, "install", "--ignore-scripts", "--no-audit", "--no-fund"],
    {
      cwd: consumer,
      encoding: "utf8",
      env: { ...process.env, NO_COLOR: "1" },
    },
  );
  if (install.status !== 0) {
    throw new Error(
      `Unable to install staged package tarballs:\n${install.stderr || install.stdout}`,
    );
  }

  const importable = packages.filter((pkg) => pkg.manifest.name !== "@wrnexus/cli");
  writeFileSync(
    join(consumer, "probe.mjs"),
    `${importable
      .map(
        (pkg) =>
          `if (!await import(${JSON.stringify(pkg.manifest.name)})) throw new Error(${JSON.stringify(`Unable to import ${pkg.manifest.name}`)});`,
      )
      .join(
        "\n",
      )}\nconsole.log(${JSON.stringify(`Imported ${importable.length} staged package roots.`)});\n`,
  );
  const probe = spawnSync(bun, ["probe.mjs"], {
    cwd: consumer,
    encoding: "utf8",
    env: { ...process.env, NO_COLOR: "1" },
  });
  if (probe.status !== 0)
    throw new Error(`Staged package import probe failed:\n${probe.stderr || probe.stdout}`);
  if (probe.stdout) process.stdout.write(probe.stdout);

  writeFileSync(
    join(consumer, "browser-probe.js"),
    'import "@wrnexus/csr";\nimport "@wrnexus/reactive";\n',
  );
  const browser = spawnSync(
    bun,
    ["build", "browser-probe.js", "--target=browser", "--outfile=browser-probe.bundle.js"],
    { cwd: consumer, encoding: "utf8", env: { ...process.env, NO_COLOR: "1" } },
  );
  if (browser.status !== 0 || !existsSync(join(consumer, "browser-probe.bundle.js"))) {
    throw new Error(`Staged browser package build failed:\n${browser.stderr || browser.stdout}`);
  }

  const cli = spawnSync(
    bun,
    [join(consumer, "node_modules", "@wrnexus", "cli", "dist", "index.js"), "--help"],
    { cwd: consumer, encoding: "utf8", env: { ...process.env, NO_COLOR: "1" } },
  );
  if (cli.status !== 0 || !/wrnexus/i.test(`${cli.stdout}\n${cli.stderr}`)) {
    throw new Error(`Staged CLI smoke test failed:\n${cli.stderr || cli.stdout}`);
  }
  console.log(
    "Staged package tarballs, browser runtime bundle, and CLI passed their isolated consumer smoke tests.",
  );
} finally {
  rmSync(consumer, { recursive: true, force: true });
}
