/*
 * Runtime storage plane / path resolver.
 * Purpose: resolve public-safe Praxis home and workspace roots without reading secrets
 * or creating directories during compile.
 */
import os from "node:os";
import path from "node:path";
import { existsSync, statSync } from "node:fs";
function failure(code, message, boundary) {
    return {
        ok: false,
        error: { code, message, boundary, publicSafe: true },
        events: ["runtime.storagePlane.path.rejected"],
    };
}
function hasText(value) {
    return typeof value === "string" && value.trim().length > 0;
}
function normalizeAbsolute(input) {
    return path.resolve(input);
}
function directoryExists(input) {
    try {
        return existsSync(input) && statSync(input).isDirectory();
    }
    catch {
        return false;
    }
}
export function resolveRaxHome(input = {}) {
    const envHome = input.env?.HOME;
    const rawHome = input.explicitHome ?? input.homeDir ?? envHome ?? os.homedir();
    const source = input.explicitHome !== undefined
        ? "explicit"
        : input.homeDir !== undefined || envHome !== undefined
            ? "env"
            : "os";
    if (!hasText(rawHome)) {
        return failure("EMPTY_PATH", "Praxis home requires a non-empty home path", "input");
    }
    if (!path.isAbsolute(rawHome)) {
        return failure("RELATIVE_HOME", "Praxis home must resolve from an absolute home path", "input");
    }
    return {
        ok: true,
        value: {
            root: path.join(normalizeAbsolute(rawHome), ".rax"),
            source,
        },
        events: ["runtime.storagePlane.home.resolved"],
    };
}
function findWorkspaceRoot(cwd, workspaceFolderName) {
    let current = normalizeAbsolute(cwd);
    while (true) {
        const candidate = path.join(current, workspaceFolderName);
        if (directoryExists(candidate)) {
            return candidate;
        }
        const parent = path.dirname(current);
        if (parent === current) {
            return undefined;
        }
        current = parent;
    }
}
export function resolveRaxWorkspace(input = {}) {
    const rawCwd = input.cwd ?? process.cwd();
    const workspaceFolderName = input.workspaceFolderName?.trim() || ".rax_workspace";
    if (!hasText(rawCwd)) {
        return failure("INVALID_CWD", "Praxis workspace resolution requires a non-empty cwd", "input");
    }
    const cwd = normalizeAbsolute(rawCwd);
    if (input.explicitWorkspaceRoot !== undefined) {
        if (!hasText(input.explicitWorkspaceRoot)) {
            return failure("EMPTY_PATH", "Praxis workspace override requires a non-empty path", "input");
        }
        const root = path.isAbsolute(input.explicitWorkspaceRoot)
            ? normalizeAbsolute(input.explicitWorkspaceRoot)
            : normalizeAbsolute(path.join(cwd, input.explicitWorkspaceRoot));
        return {
            ok: true,
            value: {
                root,
                cwd,
                source: "explicit",
                existing: directoryExists(root),
                workspaceFolderName,
            },
            events: ["runtime.storagePlane.workspace.resolved"],
        };
    }
    const discovered = findWorkspaceRoot(cwd, workspaceFolderName);
    const root = discovered ?? path.join(cwd, workspaceFolderName);
    return {
        ok: true,
        value: {
            root,
            cwd,
            source: discovered === undefined ? "planned" : "discovered",
            existing: discovered !== undefined,
            workspaceFolderName,
        },
        events: ["runtime.storagePlane.workspace.resolved"],
    };
}
export function safeAgentStorageId(agentId) {
    const trimmed = agentId.trim();
    if (!hasText(trimmed)) {
        return failure("INVALID_AGENT_ID", "Agent storage id must be non-empty", "input");
    }
    if (trimmed === "." ||
        trimmed === ".." ||
        trimmed.includes("/") ||
        trimmed.includes("\\") ||
        /[\u0000-\u001F\u007F]/u.test(trimmed)) {
        return failure("INVALID_AGENT_ID", "Agent storage id cannot contain path traversal or separators", "security");
    }
    return {
        ok: true,
        value: trimmed,
        events: ["runtime.storagePlane.agentId.accepted"],
    };
}
export function assertChildPath(parent, child) {
    const normalizedParent = normalizeAbsolute(parent);
    const normalizedChild = normalizeAbsolute(child);
    const relative = path.relative(normalizedParent, normalizedChild);
    if (relative.startsWith("..") || path.isAbsolute(relative)) {
        return failure("PATH_ESCAPE", "Resolved storage path must remain inside its parent root", "security");
    }
    return {
        ok: true,
        value: normalizedChild,
        events: ["runtime.storagePlane.path.accepted"],
    };
}
