import { getSession } from "../lib/neo4j.js";
import { assertUUID, removeAttachmentDir, } from "../lib/attachments.js";
import { softDeleteDocument, deleteDocumentChildren, deleteDocumentNode, } from "../lib/document-hierarchy.js";
// ---------------------------------------------------------------------------
// memory-delete — remove a KnowledgeDocument from the knowledge graph.
//
// Two modes:
//   soft (default)  — sets deletedAt on the document and all children.
//                     Nodes remain in the graph but are excluded from
//                     memory-search. A future hard delete purges them.
//   hard (force)    — cascade-deletes all children, the document node,
//                     and the attachment directory from disk.
//
// FIND DOC --> SOFT? --> SET deletedAt (doc + children)
//                │
//                └── HARD? --> DELETE children --> DELETE doc --> DELETE disk
// ---------------------------------------------------------------------------
const GRACE_PERIOD_DAYS = 7;
export async function memoryDelete(params) {
    const { accountId, attachmentId, force = false } = params;
    assertUUID(attachmentId, "attachmentId");
    const t0 = Date.now();
    const tag = attachmentId.slice(0, 8);
    const log = (stage, detail) => console.error(`[memory-delete] [${tag}] ${stage}${detail ? ` — ${detail}` : ""} (${Date.now() - t0}ms)`);
    const session = getSession();
    try {
        // Verify the document exists and belongs to this account
        const check = await session.run(`MATCH (d:KnowledgeDocument { attachmentId: $attachmentId, accountId: $accountId })
       RETURN d.deletedAt AS deletedAt`, { attachmentId, accountId });
        if (check.records.length === 0) {
            throw new Error(`No KnowledgeDocument found for attachmentId "${attachmentId}" in this account.`);
        }
        const existingDeletedAt = check.records[0].get("deletedAt");
        if (!force) {
            // Soft delete
            if (existingDeletedAt) {
                // Already soft-deleted — idempotent
                log("already-soft-deleted", existingDeletedAt);
                return {
                    mode: "soft",
                    attachmentId,
                    document: 0,
                    sections: 0,
                    chunks: 0,
                    references: 0,
                    diskRemoved: false,
                    deletedAt: existingDeletedAt,
                };
            }
            const now = new Date();
            const deletedAt = now.toISOString();
            const purgeDate = new Date(now);
            purgeDate.setDate(purgeDate.getDate() + GRACE_PERIOD_DAYS);
            const purgeAfter = purgeDate.toISOString();
            const result = await softDeleteDocument(attachmentId, deletedAt, session);
            log("soft-deleted", `doc=${result.document} sections=${result.sections} chunks=${result.chunks} — grace period: ${GRACE_PERIOD_DAYS} days, purge after: ${purgeAfter.slice(0, 10)}`);
            return {
                mode: "soft",
                attachmentId,
                document: result.document,
                sections: result.sections,
                chunks: result.chunks,
                references: 0,
                diskRemoved: false,
                deletedAt,
                purgeAfter,
            };
        }
        // Hard delete (force)
        log("hard-delete", "starting cascade");
        const cascade = await deleteDocumentChildren(attachmentId, session);
        log("cascade", `sections=${cascade.sections} chunks=${cascade.chunks} references=${cascade.references}`);
        const docDeleted = await deleteDocumentNode(attachmentId, session);
        log("document-deleted", docDeleted ? "removed" : "already absent");
        // Remove files from disk (no-op for web-ingested documents)
        const diskRemoved = await removeAttachmentDir(accountId, attachmentId);
        if (diskRemoved) {
            log("disk-removed", `${accountId}/${attachmentId}/`);
        }
        else {
            log("disk-skipped", "no attachment directory on disk");
        }
        return {
            mode: "hard",
            attachmentId,
            document: docDeleted ? 1 : 0,
            sections: cascade.sections,
            chunks: cascade.chunks,
            references: cascade.references,
            diskRemoved,
        };
    }
    finally {
        await session.close();
        log("complete");
    }
}
//# sourceMappingURL=memory-delete.js.map