/**
 * SOP file discovery for the Ion workflow engine.
 *
 * Locates `.sop.md` files by delegating file-system traversal to a
 * caller-provided glob function. This keeps the module pure (no Node
 * dependency) and easily testable.
 */

/**
 * A function that resolves a glob pattern to an array of absolute paths.
 *
 * The caller typically provides an implementation backed by `node:fs/promises`
 * or a test double.
 */
export type GlobFn = (pattern: string) => Promise<string[]>;

/** Default search directories (in priority order, relative to cwd). */
const SEARCH_DIRS = ['.archon/workflows', '.'];

/** Glob pattern for SOP markdown files. */
const SOP_GLOB = '**/*.sop.md';

/**
 * Discover all `.sop.md` files in the given working directory.
 *
 * Searches `.archon/workflows/` first, then the project root, and returns
 * absolute paths to every matching file. Duplicate paths are de-duplicated.
 *
 * @param cwd    - The working directory to search from.
 * @param globFn - A function that resolves a glob pattern to file paths.
 *                 Typically backed by `glob` from `node:fs/promises` or a
 *                 similar library.
 * @returns An array of absolute file paths to discovered `.sop.md` files,
 *          sorted deterministically.
 */
export async function discoverSopFiles(
  cwd: string,
  globFn: GlobFn,
): Promise<string[]> {
  const seen = new Set<string>();
  const results: string[] = [];

  for (const dir of SEARCH_DIRS) {
    const pattern =
      dir === '.' ? `${cwd}/${SOP_GLOB}` : `${cwd}/${dir}/${SOP_GLOB}`;

    let paths: string[];
    try {
      paths = await globFn(pattern);
    } catch {
      // Glob errors (e.g. directory doesn't exist) are non-fatal.
      continue;
    }

    // Sort for deterministic output and de-duplicate
    paths.sort();
    for (const p of paths) {
      if (!seen.has(p)) {
        seen.add(p);
        results.push(p);
      }
    }
  }

  return results;
}