import { spawnSync } from "node:child_process";
import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import path from "node:path";
import { afterEach, describe, expect, it } from "vitest";
import { useAutoCleanupTempDirTracker } from "../helpers/temp-dir.js";

const tempDirs = useAutoCleanupTempDirTracker(afterEach);

const installers = [
  {
    script: "scripts/install-xcodegen.sh",
    url: "https://github.com/yonaskolb/XcodeGen/releases/download/2.46.0/xcodegen.zip",
  },
  {
    script: "scripts/install-swift-tools.sh",
    url: "https://github.com/nicklockwood/SwiftFormat/releases/download/0.62.1/swiftformat.zip",
  },
] as const;

function expectOption(args: string[], option: string, value: string): void {
  const index = args.indexOf(option);
  expect(index, `missing curl option ${option}`).toBeGreaterThanOrEqual(0);
  expect(args[index + 1]).toBe(value);
}

describe.runIf(process.platform !== "win32")("native tool installers", () => {
  it.each(installers)("bounds stalled downloads in $script", ({ script, url }) => {
    const root = tempDirs.make("openclaw-native-tool-installer-");
    const binDir = path.join(root, "bin");
    const argsPath = path.join(root, "curl-args.txt");
    const curlPath = path.join(binDir, "curl");
    mkdirSync(binDir);
    writeFileSync(
      curlPath,
      [
        "#!/usr/bin/env bash",
        'printf "%s\\n" "$@" >"$OPENCLAW_TEST_CURL_ARGS_PATH"',
        "exit 28",
        "",
      ].join("\n"),
    );
    chmodSync(curlPath, 0o755);

    const result = spawnSync("bash", [script, path.join(root, "install")], {
      cwd: process.cwd(),
      encoding: "utf8",
      env: {
        ...process.env,
        OPENCLAW_TEST_CURL_ARGS_PATH: argsPath,
        PATH: `${binDir}${path.delimiter}${process.env.PATH ?? ""}`,
      },
    });

    expect(result.status, `${result.stdout}\n${result.stderr}`).toBe(28);
    const args = readFileSync(argsPath, "utf8").trimEnd().split("\n");
    expectOption(args, "--connect-timeout", "10");
    expectOption(args, "--max-time", "120");
    expectOption(args, "--retry", "3");
    expectOption(args, "--retry-max-time", "120");
    expect(args).toContain(url);
  });
});
