import path from "node:path";
function defaultCaseSensitive() {
    return process.platform !== "win32" && process.platform !== "darwin";
}
function looksWindowsLike(rawPath) {
    return /^[a-zA-Z]:[\\/]/.test(rawPath)
        || rawPath.startsWith("\\\\")
        || rawPath.includes("\\");
}
function stripTrailingSlash(value) {
    if (value === "/" || /^[a-zA-Z]:\/$/.test(value))
        return value;
    return value.replace(/\/+$/, "");
}
function isRootLike(value) {
    return value === ""
        || value === "."
        || value === "./"
        || value === "/"
        || /^[a-zA-Z]:\/?$/.test(value);
}
/**
 * Canonical path string used for comparison only.
 *
 * This intentionally detects the path grammar from the string itself instead
 * of assuming the current OS. That lets tests and adapters reason about
 * Windows paths on macOS/Linux and vice versa.
 */
export function normalizePathForComparison(rawPath, options = {}) {
    const caseSensitive = options.caseSensitive ?? defaultCaseSensitive();
    const trimmed = String(rawPath ?? "").trim();
    if (!trimmed)
        return "";
    const normalized = looksWindowsLike(trimmed)
        ? path.win32.normalize(trimmed).replace(/\\/g, "/")
        : path.posix.normalize(trimmed.replace(/\\/g, "/"));
    const withoutTrailing = stripTrailingSlash(normalized);
    return caseSensitive
        ? withoutTrailing.replace(/^([A-Z]):\//, (_, drive) => `${drive.toLowerCase()}:/`)
        : withoutTrailing.toLowerCase();
}
export function hasGlobPattern(rawPath) {
    return /[*?]/.test(String(rawPath ?? ""));
}
export function isSameOrDescendantPath(candidatePath, boundaryPath, options = {}) {
    const candidate = normalizePathForComparison(candidatePath, options);
    const boundary = normalizePathForComparison(boundaryPath, options);
    if (!candidate || !boundary)
        return false;
    if (isRootLike(boundary))
        return true;
    if (candidate === boundary)
        return true;
    return candidate.startsWith(`${boundary}/`);
}
function escapeRegex(value) {
    return value.replace(/[.+^${}()|[\]\\]/g, "\\$&");
}
function globToRegExp(pattern, options = {}) {
    const normalized = normalizePathForComparison(pattern, options);
    let source = "";
    for (let i = 0; i < normalized.length; i += 1) {
        const char = normalized[i];
        if (char === "*") {
            if (normalized[i + 1] === "*") {
                source += ".*";
                i += 1;
            }
            else {
                source += "[^/]*";
            }
        }
        else if (char === "?") {
            source += "[^/]";
        }
        else {
            source += escapeRegex(char);
        }
    }
    return new RegExp(`^${source}$`, (options.caseSensitive ?? defaultCaseSensitive()) ? "" : "i");
}
export function matchesScopePattern(candidatePath, scopePattern, options = {}) {
    const pattern = normalizePathForComparison(scopePattern, options);
    if (!pattern)
        return false;
    if (isRootLike(pattern))
        return true;
    if (/[*?]/.test(pattern)) {
        return globToRegExp(pattern, options).test(normalizePathForComparison(candidatePath, options));
    }
    return isSameOrDescendantPath(candidatePath, pattern, options);
}
export function normalizeScopePattern(rawPath, _options = {}) {
    const normalized = toPosixPath(rawPath);
    if (!normalized)
        return "";
    if (isRootLike(normalized))
        return normalized;
    if (hasGlobPattern(normalized))
        return normalized.replace(/\/+$/, "");
    return ensureTrailingSlash(normalized);
}
export function isPathInScope(candidatePath, scopePattern, options = {}) {
    if (hasGlobPattern(scopePattern)) {
        return matchesScopePattern(candidatePath, scopePattern, options);
    }
    return isSameOrDescendantPath(candidatePath, scopePattern, options);
}
export function isPathInAnyScope(candidatePath, scopePatterns, options = {}) {
    return scopePatterns.some((scopePattern) => isPathInScope(candidatePath, scopePattern, options));
}
export function toPosixPath(rawPath) {
    return normalizePathForComparison(rawPath, { caseSensitive: true }).replace(/^\.\//, "");
}
export function ensureTrailingSlash(rawPath) {
    const normalized = toPosixPath(rawPath);
    if (!normalized || normalized.endsWith("/"))
        return normalized;
    if (normalized === "." || normalized === "/")
        return normalized;
    return `${normalized}/`;
}
export function isPathInsideProject(projectRoot, targetPath, options = {}) {
    return isSameOrDescendantPath(targetPath, projectRoot, options);
}
//# sourceMappingURL=path_scope_utils.js.map