import fs from "node:fs";
import os from "node:os";
import path from "node:path";

function isExecutable(filePath: string): boolean {
  try {
    fs.accessSync(filePath, fs.constants.X_OK);
    return true;
  } catch {
    return false;
  }
}

function normalizePathValue(value: unknown): string | undefined {
  if (typeof value !== "string") {
    return undefined;
  }
  const trimmed = value.trim();
  return trimmed ? trimmed : undefined;
}

export function resolveBrewPathDirs(opts?: {
  homeDir?: string;
  env?: NodeJS.ProcessEnv;
}): string[] {
  const homeDir = opts?.homeDir ?? os.homedir();
  const env = opts?.env ?? process.env;

  const dirs: string[] = [];
  const prefix = normalizePathValue(env.HOMEBREW_PREFIX);
  if (prefix) {
    dirs.push(path.join(prefix, "bin"), path.join(prefix, "sbin"));
  }

  // Linuxbrew defaults.
  dirs.push(path.join(homeDir, ".linuxbrew", "bin"));
  dirs.push(path.join(homeDir, ".linuxbrew", "sbin"));
  dirs.push("/home/linuxbrew/.linuxbrew/bin", "/home/linuxbrew/.linuxbrew/sbin");

  // macOS defaults (also used by some Linux setups).
  dirs.push("/opt/homebrew/bin", "/usr/local/bin");

  return dirs;
}

export function resolveBrewExecutable(opts?: {
  homeDir?: string;
  env?: NodeJS.ProcessEnv;
}): string | undefined {
  const homeDir = opts?.homeDir ?? os.homedir();
  const env = opts?.env ?? process.env;

  const candidates: string[] = [];

  const brewFile = normalizePathValue(env.HOMEBREW_BREW_FILE);
  if (brewFile) {
    candidates.push(brewFile);
  }

  const prefix = normalizePathValue(env.HOMEBREW_PREFIX);
  if (prefix) {
    candidates.push(path.join(prefix, "bin", "brew"));
  }

  // Linuxbrew defaults.
  candidates.push(path.join(homeDir, ".linuxbrew", "bin", "brew"));
  candidates.push("/home/linuxbrew/.linuxbrew/bin/brew");

  // macOS defaults.
  candidates.push("/opt/homebrew/bin/brew", "/usr/local/bin/brew");

  for (const candidate of candidates) {
    if (isExecutable(candidate)) {
      return candidate;
    }
  }

  return undefined;
}
