import { execFileSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";

export type EffectiveSshConfig = Map<string, string[]>;

export function parseSshG(text: string): EffectiveSshConfig {
  const values: EffectiveSshConfig = new Map();
  for (const line of text.split(/\r?\n/)) {
    const separator = line.indexOf(" ");
    if (separator < 1) continue;
    const key = line.slice(0, separator).trim().toLowerCase();
    const value = line.slice(separator + 1).trim();
    if (!key || !value) continue;
    const current = values.get(key) ?? [];
    current.push(value);
    values.set(key, current);
  }
  return values;
}

export function resolveOpenSshAlias(alias: string): EffectiveSshConfig {
  if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(alias)) throw new Error(`invalid SSH alias: ${alias}`);
  const output = execFileSync("ssh", ["-G", "--", alias], {
    encoding: "utf8",
    stdio: ["ignore", "pipe", "pipe"],
  });
  return parseSshG(output);
}

export function effectiveValue(config: EffectiveSshConfig, key: string): string | undefined {
  return config.get(key.toLowerCase())?.at(-1);
}

export function effectiveValues(config: EffectiveSshConfig, key: string): string[] {
  return config.get(key.toLowerCase()) ?? [];
}

export function listDirectSshAliases(configPath = join(homedir(), ".ssh", "config")): string[] {
  if (!existsSync(configPath)) return [];
  const aliases: string[] = [];
  const text = readFileSync(configPath, "utf8");
  for (const line of text.split(/\r?\n/)) {
    const match = /^\s*Host\s+(.+?)\s*$/i.exec(line);
    if (!match) continue;
    for (const alias of match[1].split(/\s+/)) {
      if (!alias || alias.includes("*") || alias.includes("?") || alias.startsWith("!")) continue;
      if (!aliases.includes(alias)) aliases.push(alias);
    }
  }
  return aliases;
}
