import { describe, expect, it, vi } from "vitest";
import { RuntimeCheckFailedError, runtimeCheck } from "../../workspace/runtime-check.js";

describe("runtimeCheck", () => {
  it("reports missing wsl through the shared command helper fallback", async () => {
    const execFile = vi.fn(
      async (file: string, args: string[], _options?: { windowsHide: boolean }) => {
        if (file === "git") {
          return { stdout: "git version 2.48.0\n", stderr: "" };
        }

        if (file === "node") {
          return { stdout: "v22.15.0\n", stderr: "" };
        }

        if (file === "where" && args[0] === "wsl") {
          throw new Error("wsl unavailable");
        }

        return { stdout: "", stderr: "" };
      }
    );

    const result = await runtimeCheck("/tmp", "wsl", {
      platform: "win32",
      runCommand: execFile,
    });

    expect(result).toEqual({ ok: false, missing: ["wsl"] });
    expect(execFile).toHaveBeenCalledWith("where", ["wsl"], { windowsHide: true });
  });

  it("reports missing git and node from the version checks deterministically", async () => {
    const result = await runtimeCheck("/tmp", "native", {
      commandExists: async () => true,
      runCommand: vi.fn(async (file: string) => {
        throw new Error(`${file} unavailable`);
      }),
    });

    expect(result).toEqual({ ok: false, missing: ["git", "node"] });
  });

  it("passes windowsHide to injected execFile on Windows version checks", async () => {
    const execFile = vi.fn(
      async (file: string, _args: string[], _options?: { windowsHide: boolean }) => {
        if (file === "git") {
          return { stdout: "git version 2.48.0\n", stderr: "" };
        }

        if (file === "node") {
          return { stdout: "v22.15.0\n", stderr: "" };
        }

        throw new Error(`${file} unavailable`);
      }
    );

    const result = await runtimeCheck("/tmp", "native", {
      platform: "win32",
      runCommand: execFile,
    });

    expect(result).toEqual({ ok: true, missing: [] });
    expect(execFile).toHaveBeenCalledWith("git", ["--version"], { windowsHide: true });
    expect(execFile).toHaveBeenCalledWith("node", ["--version"], { windowsHide: true });
  });
});

describe("RuntimeCheckFailedError", () => {
  it("should create error with missing tools list", () => {
    const error = new RuntimeCheckFailedError(["git", "node"]);
    expect(error.name).toBe("RuntimeCheckFailedError");
    expect(error.message).toBe("Missing required tools: git, node");
    expect(error.missing).toEqual(["git", "node"]);
  });
});
