import { basename } from "path";
import { pathExists, readTextFile, displayProjectRootPath, } from "../../util/fs.js";
export function semverGt(a, b) {
    const pa = a.split(".").map((n) => Number.parseInt(n, 10));
    const pb = b.split(".").map((n) => Number.parseInt(n, 10));
    for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
        const na = pa[i] ?? 0;
        const nb = pb[i] ?? 0;
        if (na > nb)
            return true;
        if (na < nb)
            return false;
    }
    return false;
}
const SECRET_KEY_SUBSTRINGS = ["apikey", "token", "password", "secret", "authorization", "bearer", "key"];
export function isSecretKey(key) {
    const lk = key.toLowerCase();
    return SECRET_KEY_SUBSTRINGS.some((sk) => lk === sk || lk.endsWith(sk));
}
export function redactSecrets(obj) {
    if (typeof obj === "string")
        return obj;
    if (typeof obj !== "object" || obj === null)
        return obj;
    if (Array.isArray(obj))
        return obj.map(redactSecrets);
    const result = {};
    for (const [key, value] of Object.entries(obj)) {
        if (typeof value === "string" && isSecretKey(key)) {
            result[key] = "***";
        }
        else {
            result[key] = redactSecrets(value);
        }
    }
    return result;
}
export function isNpmLauncherCommand(command) {
    if (!command)
        return false;
    const executable = command.trim().split(/\s+/)[0];
    if (!executable)
        return false;
    const name = basename(executable).toLowerCase();
    return ["npm", "npx", "npm.cmd", "npx.cmd", "npm.exe", "npx.exe"].includes(name);
}
export function isExpectedGlobalKimiFile(name) {
    const expected = new Set([
        "AGENTS.md",
        "ENI.md",
        "Jailbreak.md",
        "PARALLEL_AGENTS.md",
        "User.md",
        "agent.yaml",
        "config.toml",
        "device_id",
        "kimi.json",
        "latest_version.txt",
        "mcp-web-search.sh",
        "mcp.json",
        "mcp.manifest.json",
        "omk.memory.toml",
        "setup.md",
        "system.md",
        "user.md",
    ]);
    return (expected.has(name)
        || /^config\.toml\.bak(?:[-_].*)?$/.test(name)
        || /^mcp(?:\.manifest)?\.json\.bak(?:[-_].*)?$/.test(name)
        || /^eggup-\d+\.json$/i.test(name)
        || /\.json:Zone\.Identifier$/i.test(name));
}
export async function inspectJsonFile(filePath) {
    if (!(await pathExists(filePath)))
        return { path: filePath, exists: false, valid: false };
    try {
        JSON.parse(await readTextFile(filePath, "{}"));
        return { path: filePath, exists: true, valid: true };
    }
    catch (err) {
        const message = err instanceof Error ? err.message : String(err);
        return { path: filePath, exists: true, valid: false, error: `Invalid JSON: ${message}` };
    }
}
export function isRecord(value) {
    return typeof value === "object" && value !== null && !Array.isArray(value);
}
export function rootDiagnosticData(resolution) {
    return {
        activeCwd: displayProjectRootPath(resolution.cwd, resolution.home),
        detectedGitRoot: displayProjectRootPath(resolution.gitRoot, resolution.home),
        effectiveProjectRoot: displayProjectRootPath(resolution.root, resolution.home),
        source: resolution.source,
        marker: resolution.marker ?? null,
        homeIsGitRepo: resolution.homeIsGitRepo,
        isHomeRoot: resolution.isHomeRoot,
        defaultProjectRoot: displayProjectRootPath(resolution.configuredDefaultProjectRoot, resolution.home),
        defaultProjectRootError: resolution.defaultProjectRootError ?? null,
        warning: resolution.warning ?? null,
        recommendation: resolution.recommendation ?? null,
        fixCommand: resolution.isHomeRoot && resolution.homeIsGitRepo
            ? "omk doctor --fix --set-default-project-root /path/to/project"
            : null,
    };
}
export function safeOperationId(prefix, value) {
    const suffix = value.replace(/[^A-Za-z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
    return suffix ? `${prefix}-${suffix}` : prefix;
}
export async function readJsonValue(filePath) {
    if (!(await pathExists(filePath)))
        return { exists: false, valid: false };
    try {
        return { exists: true, valid: true, value: JSON.parse(await readTextFile(filePath, "{}")) };
    }
    catch (err) {
        return {
            exists: true,
            valid: false,
            error: err instanceof Error ? err.message : String(err),
        };
    }
}
