/**
 * Memory handler group: store, recall, stats, temporal_query, export, backup,
 * import, maintain, openclaw_sync, trace, update, delete, history, feedback,
 * hygiene, operative_journal, selection_ledger, memory_audit.
 * Extracted from mcp.ts (Phase 3 split).
 */
import { formatBullets, formatJsonDetails } from '../helpers.js';
import { nexusEventBus } from '../../../../engines/event-bus.js';
import { getOperativeJournal } from '../../../../engines/operative-journal.js';
import { requireRuntime } from '../util/require-runtime.js';
import { nxlResult } from '../../../../nxl/index.js';
import { consolidateMemory } from '../../../../engines/memory-consolidator.js';
import { recordFirstMemory } from '../../../../engines/telemetry.js';
function memoryScopeForTags(tags) {
    return tags.some((tag) => tag.startsWith('#project')) ? 'project' : 'session';
}
function memoryStatusSummary(hctx) {
    try {
        const stats = hctx.nexusRef.getMemoryStats?.();
        const health = typeof hctx.nexusRef.getMemoryHealth === 'function'
            ? hctx.nexusRef.getMemoryHealth()
            : null;
        const healthText = health
            ? `${health.active} active, ${health.quarantined} quarantined, ${health.shared} shared`
            : null;
        const topTags = Array.isArray(stats?.topTags) && stats.topTags.length
            ? stats.topTags.slice(0, 4).join(', ')
            : 'none yet';
        const tierText = stats
            ? `${stats.prefrontal} working, ${stats.hippocampus} episodic, ${stats.cortex} semantic`
            : null;
        return [
            'Memory status:',
            tierText,
            healthText,
            `top tags ${topTags}`,
        ].filter(Boolean).join(' ');
    }
    catch {
        return null;
    }
}
export async function handleMemoryGroup(toolName, hctx, request, args, ctx) {
    const runtimeError = requireRuntime(hctx);
    if (runtimeError)
        return runtimeError;
    switch (toolName) {
        case 'nexus_store_memory': {
            const content = String(request.params.arguments?.content ?? '');
            const priority = Number(request.params.arguments?.priority ?? 0.7);
            const tags = Array.isArray(request.params.arguments?.tags)
                ? request.params.arguments.tags.map(String)
                : [];
            const verbatim = Boolean(request.params.arguments?.verbatim ?? false);
            const id = hctx.nexusRef.storeMemory(content, priority, tags, undefined, undefined, { verbatim, agentId: hctx.getToolProfile() });
            hctx.telemetry.recordStore();
            void recordFirstMemory().catch(() => { });
            hctx.sessionDNA.recordMemoryStore();
            const nudge = hctx.telemetry.planningNudge('store', { priority });
            const scope = memoryScopeForTags(tags);
            const status = memoryStatusSummary(hctx);
            if (ctx) {
                ctx.meta.memoryScope = scope;
            }
            // Console ASCII UI
            hctx.box('🧠 CORTEX MEMORY STORED', [
                `Priority: ${priority.toFixed(2).padEnd(5)} Tags: ${tags.join(', ').substring(0, 31).padEnd(31)}`,
                `${content.substring(0, 56).padEnd(56, ' ').replace(/\n/g, ' ')}...`,
            ], '36');
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory stored. ID: ' + id,
                            `Memory link: ${scope} scope, priority ${priority.toFixed(2)}, ${tags.length} tag(s).`,
                            status,
                            nudge,
                        ].filter(Boolean).join('\n\n'),
                    }],
            };
        }
        case 'nexus_recall_memory': {
            const query = String(request.params.arguments?.query ?? '');
            const k = Number(request.params.arguments?.k ?? 5);
            const fmt = String(request.params.arguments?.format ?? 'text');
            const crossClient = Boolean(request.params.arguments?.cross_client ?? false);
            const memories = await hctx.nexusRef.recallMemory(query, k, crossClient ? undefined : hctx.getToolProfile());
            const preview = memories.slice(0, 3).map((m) => String(m ?? '').replace(/\s+/g, ' ').slice(0, 96));
            nexusEventBus.emit('memory.recall', { query, count: memories.length, k, crossClient, format: fmt, preview });
            hctx.telemetry.recordRecall(memories.length);
            hctx.sessionDNA.recordMemoryRecall();
            if (ctx) {
                ctx.meta.memoryRecallCount = memories.length;
            }
            const nudge = hctx.telemetry.planningNudge('recall', { count: memories.length });
            const status = memoryStatusSummary(hctx);
            // Console ASCII UI
            hctx.box('🔍 CORTEX MEMORY RECALL', [
                `Query: ${query.replace(/\n/g, ' ').substring(0, 57).padEnd(59, ' ')}`,
                `Retrieved: ${memories.length.toString().padEnd(55, ' ')}`
            ], '35');
            if (fmt === 'nxl')
                return nxlResult({ query, count: memories.length, memories });
            // Token-economy: truncate each body to 280 chars by default. Pass
            // format='full' to opt back into verbatim output. Verified savings
            // are typically 4-6× on recall payloads.
            const RECALL_BODY_LIMIT = 280;
            const truncate = fmt !== 'full';
            const formatted = memories.map((m, i) => {
                const body = String(m ?? '');
                if (!truncate || body.length <= RECALL_BODY_LIMIT)
                    return `${i + 1}. ${body}`;
                return `${i + 1}. ${body.slice(0, RECALL_BODY_LIMIT)}… [truncated; pass format="full" for verbatim]`;
            }).join('\n\n');
            return {
                content: [{
                        type: 'text',
                        text: [
                            memories.length > 0
                                ? `Memory recall connected ${memories.length} item(s) for "${query}".\n\n${formatted}`
                                : `No memories found for "${query}". Fresh session or new topic.`,
                            status,
                            nudge,
                        ].filter(Boolean).join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_stats': {
            const stats = hctx.nexusRef.getMemoryStats();
            const health = typeof hctx.nexusRef.getMemoryHealth === 'function'
                ? hctx.nexusRef.getMemoryHealth()
                : undefined;
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory inventory ready.',
                            formatBullets([
                                `Prefrontal: ${stats.prefrontal} item(s)`,
                                `Hippocampus: ${stats.hippocampus} item(s)`,
                                `Cortex: ${stats.cortex} item(s)`,
                                `Zettelkasten links: ${stats.totalLinks}`,
                                `Schema version: ${stats.schemaVersion ?? 0}`,
                                `Quarantine backlog: ${stats.quarantineBacklog ?? 0}`,
                                `Purge eligible: ${stats.purgeEligible ?? 0}`,
                                `Top tags: ${stats.topTags.join(', ') || 'none yet'}`,
                                stats.oldestEntry
                                    ? `Oldest entry: ${new Date(stats.oldestEntry).toLocaleDateString()}`
                                    : 'Oldest entry: none yet',
                                health ? `Health: ${health.active} active · ${health.quarantined} quarantined · ${health.shared} shared · hygiene ${health.lastHygieneAt ? new Date(health.lastHygieneAt).toLocaleString() : 'pending'}` : null,
                            ]),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_temporal_query': {
            const tQuery = String(request.params.arguments?.query ?? '');
            const atRaw = request.params.arguments?.at;
            let atMs = Date.now();
            if (atRaw != null) {
                const parsed = typeof atRaw === 'number' ? atRaw : Date.parse(String(atRaw));
                if (!Number.isNaN(parsed))
                    atMs = parsed;
            }
            const tK = Number(request.params.arguments?.k ?? 10);
            const graphMemory = hctx.nexusRef.getGraphMemory?.();
            if (!graphMemory) {
                return { content: [{ type: 'text', text: 'Graph memory not available. Ensure nexus_session_bootstrap has been called.' }] };
            }
            const results = graphMemory.temporalQuery(tQuery, atMs, tK);
            const atLabel = new Date(atMs).toISOString();
            if (!results.length) {
                return { content: [{ type: 'text', text: `No knowledge graph entries found for "${tQuery}" at ${atLabel}.` }] };
            }
            const lines = results.map((r, i) => {
                const validFrom = new Date(r.validFrom).toISOString();
                const validUntil = r.validUntil ? new Date(r.validUntil).toISOString() : 'present';
                return `${i + 1}. [${r.entityName}] ${r.content}\n   valid: ${validFrom} → ${validUntil}`;
            });
            return {
                content: [{
                        type: 'text',
                        text: `Temporal query: "${tQuery}" at ${atLabel}\n\n${lines.join('\n\n')}`,
                    }],
            };
        }
        case 'nexus_memory_export': {
            const result = hctx.nexusRef.exportMemoryBundle({
                limit: request.params.arguments?.limit == null ? undefined : Number(request.params.arguments.limit),
                scope: request.params.arguments?.scope ? String(request.params.arguments.scope) : undefined,
                state: request.params.arguments?.state ? String(request.params.arguments.state) : undefined,
                sessionId: request.params.arguments?.sessionId ? String(request.params.arguments.sessionId) : undefined,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory export ready.',
                            formatBullets([
                                `Bundle version: ${Number(result?.version || 0)}`,
                                `Schema: ${result?.schemaVersion || 'legacy'}`,
                                `Session: ${result?.sessionId || 'n/a'}`,
                                `Items: ${Number(result?.items?.length || 0)}`,
                                `Generated: ${result?.exportedAt ? new Date(result.exportedAt).toISOString() : 'n/a'}`,
                            ]),
                            formatJsonDetails('Structured details', result ?? {}),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_backup': {
            const result = hctx.nexusRef.backupMemoryBundle({
                limit: request.params.arguments?.limit == null ? undefined : Number(request.params.arguments.limit),
                scope: request.params.arguments?.scope ? String(request.params.arguments.scope) : undefined,
                state: request.params.arguments?.state ? String(request.params.arguments.state) : undefined,
                sessionId: request.params.arguments?.sessionId ? String(request.params.arguments.sessionId) : undefined,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory backup written.',
                            formatBullets([
                                `Path: ${result?.path || 'n/a'}`,
                                `Session: ${result?.bundle?.sessionId || 'n/a'}`,
                                `Items: ${Number(result?.bundle?.items?.length || 0)}`,
                            ]),
                            formatJsonDetails('Structured details', result ?? {}),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_import': {
            const result = await hctx.nexusRef.importMemoryBundle({
                path: request.params.arguments?.path ? String(request.params.arguments.path) : undefined,
                bundle: request.params.arguments?.bundle,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory import complete.',
                            formatBullets([
                                `Imported: ${Number(result?.imported || 0)}`,
                                `Added: ${Number(result?.added || 0)}`,
                                `Updated: ${Number(result?.updated || 0)}`,
                                `Skipped: ${Number(result?.skipped || 0)}`,
                                `Duplicates skipped: ${Number(result?.duplicates || 0)}`,
                                `Quarantined on import: ${Number(result?.quarantined || 0)}`,
                            ]),
                            formatJsonDetails('Structured details', result ?? {}),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_trace': {
            const id = String(request.params.arguments?.id ?? '');
            const detail = hctx.nexusRef.traceMemory(id);
            if (!detail) {
                return {
                    content: [{
                            type: 'text',
                            text: `Memory trace unavailable for ${id}.`,
                        }],
                };
            }
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory trace ready.',
                            formatBullets([
                                `ID: ${detail.id}`,
                                `Scope: ${detail.scope} · state ${detail.state} · source ${detail.source}`,
                                `Importance: ${Number(detail.importanceScore || 0).toFixed(2)} · relevance ${Number(detail.relevanceScore || 0).toFixed(2)} · trust ${Number(detail.trustScore || 0).toFixed(2)}`,
                                `Lineage: ${detail.lineage?.length || 0} item(s) · backlinks ${detail.linkedMemories?.length || 0}`,
                                `Reconciliation: ${detail.reconciliation?.action || 'none recorded'}`,
                            ]),
                            formatJsonDetails('Structured details', detail),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_update': {
            const id = String(request.params.arguments?.id ?? '');
            const result = hctx.nexusRef.updateMemory(id, {
                content: request.params.arguments?.content == null ? undefined : String(request.params.arguments.content),
                priority: request.params.arguments?.priority == null ? undefined : Number(request.params.arguments.priority),
                tags: Array.isArray(request.params.arguments?.tags)
                    ? request.params.arguments.tags.map(String)
                    : undefined,
                scope: request.params.arguments?.scope ? String(request.params.arguments.scope) : undefined,
                state: request.params.arguments?.state ? String(request.params.arguments.state) : undefined,
                trust: request.params.arguments?.trust == null ? undefined : Number(request.params.arguments.trust),
                expiresAt: request.params.arguments?.expiresAt == null ? undefined : Number(request.params.arguments.expiresAt),
                retentionHint: request.params.arguments?.retentionHint ? String(request.params.arguments.retentionHint) : undefined,
                provenance: request.params.arguments?.provenance,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            result.updated ? 'Memory updated.' : `Memory update skipped for ${id}.`,
                            result.updated
                                ? formatBullets([
                                    `ID: ${result.item?.id || id}`,
                                    `Scope: ${result.item?.scope || 'n/a'} · state ${result.item?.state || 'n/a'}`,
                                    `History event: ${result.historyEntry?.eventType || 'updated'}`,
                                ])
                                : null,
                            formatJsonDetails('Structured details', result ?? {}),
                        ].filter(Boolean).join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_delete': {
            const id = String(request.params.arguments?.id ?? '');
            const result = hctx.nexusRef.deleteMemory(id, {
                hardDelete: Boolean(request.params.arguments?.hardDelete),
                reason: request.params.arguments?.reason ? String(request.params.arguments.reason) : undefined,
                provenance: request.params.arguments?.provenance,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            result.deleted ? 'Memory deleted.' : `Memory delete skipped for ${id}.`,
                            result.deleted
                                ? formatBullets([
                                    `ID: ${result.item?.id || id}`,
                                    `Mode: ${result.hardDelete ? 'hard delete' : 'soft delete'}`,
                                    `History event: ${result.historyEntry?.eventType || 'deleted'}`,
                                ])
                                : null,
                            formatJsonDetails('Structured details', result ?? {}),
                        ].filter(Boolean).join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_history': {
            const id = String(request.params.arguments?.id ?? '');
            const limit = Number(request.params.arguments?.limit ?? 20);
            const result = hctx.nexusRef.getMemoryHistory(id, limit);
            return {
                content: [{
                        type: 'text',
                        text: [
                            `Memory history ready for ${id}.`,
                            formatBullets([
                                `Entries: ${result.length}`,
                                `Latest event: ${result[0]?.eventType || 'none'}`,
                            ]),
                            formatJsonDetails('Structured details', result),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_feedback': {
            const id = String(request.params.arguments?.id ?? '');
            const result = hctx.nexusRef.submitMemoryFeedback(id, {
                reaction: request.params.arguments?.reaction ? String(request.params.arguments.reaction) : undefined,
                rating: request.params.arguments?.rating == null ? undefined : Number(request.params.arguments.rating),
                note: request.params.arguments?.note ? String(request.params.arguments.note) : undefined,
                provenance: request.params.arguments?.provenance,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            result.accepted ? 'Memory feedback recorded.' : `Memory feedback skipped for ${id}.`,
                            result.accepted
                                ? formatBullets([
                                    `ID: ${result.item?.id || id}`,
                                    `Priority: ${Number(result.priority ?? 0).toFixed(2)}`,
                                    `Trust: ${Number(result.trust ?? 0).toFixed(2)}`,
                                ])
                                : null,
                            formatJsonDetails('Structured details', result ?? {}),
                        ].filter(Boolean).join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_hygiene': {
            const limit = Number(request.params.arguments?.limit ?? 80);
            const rawMode = String(request.params.arguments?.mode ?? 'report');
            const mode = rawMode === 'apply' || Boolean(request.params.arguments?.apply)
                ? 'apply'
                : rawMode === 'consolidate' ? 'consolidate' : 'report';
            // Consolidation mode: cluster + promote hippocampus entries
            if (mode === 'consolidate') {
                const db = hctx.nexusRef.memoryEngine?.db;
                if (!db)
                    return { content: [{ type: 'text', text: '❌ Memory DB not accessible for consolidation.' }] };
                const result = await consolidateMemory(db, {
                    minAgeMs: request.params.arguments?.minAgeMs != null ? Number(request.params.arguments.minAgeMs) : undefined,
                    minClusterSize: request.params.arguments?.minClusterSize != null ? Number(request.params.arguments.minClusterSize) : undefined,
                });
                return {
                    content: [{
                            type: 'text',
                            text: [
                                '✅ Memory consolidation complete.',
                                `  Clusters processed: ${result.clustersProcessed}`,
                                `  Entries archived:   ${result.entriesArchived}`,
                                `  Cortex memories promoted: ${result.memoriesPromoted}`,
                            ].join('\n'),
                        }],
                };
            }
            const batchSize = Math.max(1, Math.min(Number(request.params.arguments?.batchSize ?? 250), 250));
            const states = Array.isArray(request.params.arguments?.states)
                ? request.params.arguments.states.map(String).filter(Boolean)
                : undefined;
            const result = hctx.nexusRef.runMemoryHygiene({
                mode,
                batchSize,
                states,
                auditLimit: limit,
            });
            // Surface hygiene-sweep on the SSE feed; do not persist as a memory.
            try {
                nexusEventBus.emit('memory.snapshot', {
                    kind: 'hygiene-sweep',
                    mode,
                    scanned: result.audit.scanned,
                    purgeEligible: result.health.purgeEligible,
                    quarantineBacklog: result.health.quarantineBacklog,
                });
            }
            catch { /* best-effort */ }
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Memory hygiene report ready.',
                            formatBullets([
                                `Mode: ${result.mode}`,
                                `Schema: ${Number(result.schemaVersion || 0)}`,
                                `Scanned: ${Number(result.audit.scanned || 0)}`,
                                `Quarantine backlog: ${Number(result.health.quarantineBacklog || 0)}`,
                                `Purge eligible: ${Number(result.health.purgeEligible || 0)}`,
                                `Promoted: ${Number(result.health.promoted || 0)}`,
                                `Shared: ${Number(result.health.shared || 0)}`,
                            ]),
                            formatJsonDetails('Structured details', {
                                ...result,
                            }),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_operative_journal': {
            const ojAction = String(request.params.arguments?.action ?? 'list');
            const ojOperativeId = request.params.arguments?.operativeId ? String(request.params.arguments.operativeId) : undefined;
            const ojContent = request.params.arguments?.content ? String(request.params.arguments.content) : undefined;
            const ojTags = Array.isArray(request.params.arguments?.tags)
                ? request.params.arguments.tags.map(String)
                : [];
            const ojLimit = Number(request.params.arguments?.limit ?? 20);
            const journal = getOperativeJournal();
            if (ojAction === 'append') {
                if (!ojOperativeId)
                    return { content: [{ type: 'text', text: 'operativeId is required for append.' }] };
                if (!ojContent)
                    return { content: [{ type: 'text', text: 'content is required for append.' }] };
                const sessionId = hctx.nexusRef.getOrchestrator?.().getSessionState?.()?.sessionId;
                const entry = journal.append(ojOperativeId, ojContent, ojTags, sessionId);
                return { content: [{ type: 'text', text: `Journal entry appended for operative ${ojOperativeId}. Entry ID: ${entry.id}` }] };
            }
            if (ojAction === 'read') {
                if (!ojOperativeId)
                    return { content: [{ type: 'text', text: 'operativeId is required for read.' }] };
                const entries = journal.read(ojOperativeId).slice(-ojLimit);
                if (!entries.length)
                    return { content: [{ type: 'text', text: `No journal entries found for operative ${ojOperativeId}.` }] };
                const lines = entries.map((e, i) => `${i + 1}. [${new Date(e.timestamp).toISOString()}] ${e.content}${e.tags.length ? ' (' + e.tags.join(', ') + ')' : ''}`);
                return { content: [{ type: 'text', text: `Journal for ${ojOperativeId} (${entries.length} entries):\n\n${lines.join('\n\n')}` }] };
            }
            if (ojAction === 'recent') {
                const entries = journal.recent(ojLimit);
                if (!entries.length)
                    return { content: [{ type: 'text', text: 'No operative journal entries found.' }] };
                const lines = entries.map((e, i) => `${i + 1}. [${e.operativeId}] [${new Date(e.timestamp).toISOString()}] ${e.content}`);
                return { content: [{ type: 'text', text: `Recent journal entries (${entries.length}):\n\n${lines.join('\n\n')}` }] };
            }
            // list
            const operatives = journal.listOperatives();
            if (!operatives.length)
                return { content: [{ type: 'text', text: 'No operative journals found. Use action=append to create the first entry.' }] };
            return { content: [{ type: 'text', text: `Operatives with journals (${operatives.length}):\n\n${operatives.join('\n')}` }] };
        }
        case 'nexus_selection_ledger': {
            const usage = hctx.getRuntime().getUsageSnapshot();
            const payload = {
                selectionAudit: usage?.artifactSelectionAudit ?? { selected: [], rejected: [], summary: 'No selection audit recorded yet.' },
                executionLedger: usage?.executionLedger ?? null,
                instructionPacket: usage?.instructionPacket ?? null,
            };
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Selection ledger ready.',
                            formatBullets([
                                `Selected assets: ${payload.selectionAudit.selected?.length || 0}`,
                                `Rejected assets: ${payload.selectionAudit.rejected?.length || 0}`,
                                `Ledger present: ${payload.executionLedger ? 'yes' : 'no'}`,
                            ]),
                            formatJsonDetails('Structured details', payload),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_memory_audit': {
            const limit = Number(request.params.arguments?.limit ?? 80);
            const audit = hctx.getRuntime().auditMemory(limit) ?? { scanned: 0, quarantined: [], findings: [] };
            nexusEventBus.emit('memory.audit', { scanned: audit.scanned, quarantined: audit.quarantined.length });
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify(audit, null, 2),
                    }],
            };
        }
    }
    return undefined;
}
