import { resolve } from "node:path";
import { readFile, readdir, rm } from "node:fs/promises";
import { existsSync } from "node:fs";
// ---------------------------------------------------------------------------
// Shared attachment helpers for memory MCP tools.
//
// Path derivation: PLATFORM_ROOT (env or dirname-based) → ../data/uploads/
// Uploads live at {installDir}/data/uploads/ — outside the platform/ wipe zone
// so user-uploaded files survive reinstalls.
// ---------------------------------------------------------------------------
const PLATFORM_ROOT = process.env.PLATFORM_ROOT ?? resolve(import.meta.dirname, "../../../..");
export const ATTACHMENTS_ROOT = resolve(PLATFORM_ROOT, "..", "data/uploads");
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
/**
 * Validate that a value is a UUID. Throws if not — prevents path traversal
 * when constructing filesystem paths from user-supplied input.
 */
export function assertUUID(value, label) {
    if (!UUID_RE.test(value)) {
        throw new Error(`Invalid ${label}: "${value}" is not a valid UUID. ` +
            `Expected format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`);
    }
}
/**
 * Resolve the directory for a specific attachment under an account.
 * Returns the absolute path. Does NOT verify existence.
 */
export function attachmentDir(accountId, attachmentId) {
    assertUUID(accountId, "accountId");
    return resolve(ATTACHMENTS_ROOT, accountId, attachmentId);
}
/**
 * Read the .meta.json sidecar for an attachment.
 * Returns null if the directory or meta file doesn't exist.
 * Throws on parse errors (corrupt meta = caller's problem).
 */
export async function readMeta(accountId, attachmentId) {
    const dir = attachmentDir(accountId, attachmentId);
    const metaPath = resolve(dir, `${attachmentId}.meta.json`);
    if (!existsSync(metaPath))
        return null;
    const raw = await readFile(metaPath, "utf-8");
    return JSON.parse(raw);
}
/**
 * Find the data file (non-.meta.json) in an attachment directory.
 * Returns the absolute path, or null if no data file exists.
 */
export async function findDataFile(accountId, attachmentId) {
    const dir = attachmentDir(accountId, attachmentId);
    if (!existsSync(dir))
        return null;
    const entries = await readdir(dir);
    const dataFile = entries.find((f) => !f.endsWith(".meta.json"));
    return dataFile ? resolve(dir, dataFile) : null;
}
/**
 * Remove an attachment directory from disk.
 * No-op if the directory doesn't exist (web-ingested documents have no file).
 * Returns true if a directory was removed, false if it didn't exist.
 */
export async function removeAttachmentDir(accountId, attachmentId) {
    const dir = attachmentDir(accountId, attachmentId);
    if (!existsSync(dir))
        return false;
    await rm(dir, { recursive: true, force: true });
    return true;
}
//# sourceMappingURL=attachments.js.map