/**
 * Filesystem autocomplete for project path creation.
 *
 * When a user types a partial path in the New Project form, the browser
 * sends `GET /api/paths/autocomplete?prefix=<partial>`. This handler
 * expands the prefix (tilde → $HOME, relative → absolute), lists the
 * containing directory, and returns up to 10 directory suggestions whose
 * basenames start with the typed partial segment.
 *
 * Two strategies:
 *   1. If the expanded prefix exists on disk as a directory — show its
 *      immediate children (trailing separator is implicit). This is the
 *      natural behaviour when the user has already typed a real directory
 *      and wants to drill deeper.
 *   2. Otherwise — split into parent + basename prefix and do a
 *      starts-with match so the user can filter siblings while typing.
 *
 * Dotfiles are excluded — they are rarely intentional project roots.
 * Symlinks to directories ARE included (readdirSync with withFileTypes
 * returns true for both real dirs and symlink dirs).
 *
 * Thread-safety: synchronous, called from the relay-dispatcher hot path.
 * fs ops block the event loop for microseconds on local SSDs; the form
 * is typed by a single human, so this is perfectly fine.
 */
import { readdirSync, statSync } from "node:fs";
import { join, sep } from "node:path";
import { expandPath } from "../paths.js";
/** Maximum number of suggestions returned to the UI. */
const MAX_SUGGESTIONS = 10;
/**
 * Build a suggestion list from `parentDir`, filtering directories whose
 * basename starts with `basenamePrefix` (case-sensitive, POSIX).
 *
 * Dotfiles are always excluded. Returns at most `MAX_SUGGESTIONS` entries.
 */
function collectSuggestions(parentDir, basenamePrefix) {
    try {
        const entries = readdirSync(parentDir, { withFileTypes: true });
        return entries
            .filter((e) => e.isDirectory() &&
            e.name.startsWith(basenamePrefix) &&
            !e.name.startsWith("."))
            .map((e) => join(parentDir, e.name))
            .slice(0, MAX_SUGGESTIONS);
    }
    catch {
        // Directory doesn't exist or is unreadable → empty list.
        return [];
    }
}
/**
 * List directory suggestions for the given path prefix.
 *
 * Examples (assume $HOME=/Users/alice, dirs are `projects`, `proj-old`,
 * `Documents`, `.config`):
 *   prefix="~"         → expanded="/Users/alice" (exists as dir)
 *                        → children of /Users/alice/  ["projects","proj-old","Documents"]
 *   prefix="~/pro"     → expanded="/Users/alice/pro" (does NOT exist)
 *                        → starts-with "pro" in /Users/alice/  ["projects","proj-old"]
 *   prefix="~/projects/" → expanded="/Users/alice/projects/" (exists as dir)
 *                        → children of /Users/alice/projects/
 *   prefix="~/projects/sr" → expanded="/Users/alice/projects/sr" (does NOT exist)
 *                        → starts-with "sr" in /Users/alice/projects/
 */
export function handlePathAutocomplete(prefix) {
    const expanded = expandPath(prefix);
    // Strategy 1: expanded path is an existing directory → show children.
    try {
        const st = statSync(expanded);
        if (st.isDirectory()) {
            const parentDir = expanded.endsWith(sep) ? expanded : expanded + sep;
            const suggestions = collectSuggestions(parentDir, "");
            return { suggestions, expandedPrefix: expanded };
        }
    }
    catch {
        // Not a directory or doesn't exist — fall through to prefix matching.
    }
    // Strategy 2: expanded path doesn't exist (or exists but isn't a dir).
    // Split into parent directory + basename prefix and match by starts-with.
    const lastSep = expanded.lastIndexOf(sep);
    let parentDir;
    let basenamePrefix;
    if (lastSep < 0) {
        // Shouldn't happen after expandPath, but be defensive.
        parentDir = expanded;
        basenamePrefix = "";
    }
    else {
        parentDir = expanded.slice(0, lastSep + 1);
        basenamePrefix = expanded.slice(lastSep + 1);
    }
    const suggestions = collectSuggestions(parentDir, basenamePrefix);
    return { suggestions, expandedPrefix: expanded };
}
