/**
 * Runtime handler group: license_usage, describe_tool, search, token_report,
 * session_search, channel_map_thread, channel_artifact_envelope,
 * federation_status, run_status.
 * Extracted from mcp.ts (Phase 3 split).
 */
import { formatBullets, formatJsonDetails, truncateText, buildAutoMemorySummary, } from '../helpers.js';
import { nexusEventBus } from '../../../../engines/event-bus.js';
import { getSharedLicenseManager, snapshotPCU, formatPCUStatus } from '../../../../licensing/index.js';
import { TokenAnalyticsEngine } from '../../../../engines/token-analytics.js';
import * as path from 'path';
import { requireRuntime } from '../util/require-runtime.js';
import { getAsyncGate } from '../async-gate.js';
import { getRun as getOrchRun } from '../../../../engines/orchestrator/store.js';
import { nxlResult } from '../../../../nxl/index.js';
import { summarizeUserWorkflowTrace } from '../../../../engines/user-workflow-trace.js';
export async function handleRuntimeGroup(toolName, hctx, request, args, ctx) {
    const runtimeError = requireRuntime(hctx);
    if (runtimeError)
        return runtimeError;
    switch (toolName) {
        case 'nexus_license_usage': {
            const fmt = String(request.params.arguments?.format ?? 'summary');
            const memStats = hctx.nexusRef.getMemoryStats();
            const pcu = snapshotPCU({
                memoryTotal: memStats?.total ?? 0,
                operativeCount: 0, // TODO: wire synapse operative count
                tokensSaved: 0,
                usdSaved: 0,
                orchestrations: 0,
                sessions: 0,
            });
            if (fmt === 'json') {
                return { content: [{ type: 'text', text: JSON.stringify(pcu, null, 2) }] };
            }
            if (fmt === 'bars') {
                return { content: [{ type: 'text', text: formatPCUStatus(pcu) }] };
            }
            // summary (default)
            const licStatus = getSharedLicenseManager().getStatus();
            const trialLines = licStatus.trialPhase ? [
                `- **Trial phase**: ${licStatus.trialPhase}`,
                typeof licStatus.trialDaysRemaining === 'number'
                    ? `- **Trial remaining**: ${licStatus.trialDaysRemaining} day${licStatus.trialDaysRemaining === 1 ? '' : 's'}`
                    : '',
                licStatus.activationRequired
                    ? `- **Agent motion**: License activation is required for paid-tier work; keep license/status tools available.`
                    : licStatus.trialPhase === 'activation'
                        ? `- **Agent motion**: Trial remains active; ask the user to request or activate a license soon, then keep working.`
                        : `- **Agent motion**: No license is mandatory during the first 3 days; ask the user to request a license soon.`,
            ].filter((line) => Boolean(line)) : [];
            const lines = [
                `## License Status`,
                `- **Plan**: ${pcu.tier.toUpperCase()}`,
                `- **Status**: ${licStatus.valid ? 'Active' : licStatus.degradedReason ?? 'Inactive'}`,
                licStatus.expiresAt ? `- **Expires**: ${new Date(licStatus.expiresAt).toISOString().split('T')[0]}` : '- **Expires**: Never',
                ...trialLines,
                '',
                `## Resource Usage`,
                `- Memory: ${pcu.memory.current.toLocaleString()} / ${Number.isFinite(pcu.memory.limit) ? pcu.memory.limit.toLocaleString() : '∞'} (${pcu.memory.pct}%)`,
                `- Projects: ${pcu.projects.current} / ${Number.isFinite(pcu.projects.limit) ? pcu.projects.limit.toLocaleString() : '∞'} (${pcu.projects.pct}%)`,
                `- Operatives: ${pcu.operatives.current} / ${Number.isFinite(pcu.operatives.limit) ? pcu.operatives.limit.toLocaleString() : '∞'} (${pcu.operatives.pct}%)`,
                `- Skills: ${pcu.skillProfile.allowed}`,
                `- Darwin: ${pcu.darwin.enabled ? pcu.darwin.scope : 'off'}`,
                '',
                `## Upgrade`,
                `- Dashboard: http://127.0.0.1:3377 → License tab`,
                `- Web: https://nexus-prime.cfd/account`,
                `- Email: adarsh@nexus-prime.cfd`,
                `- SLA: team will share licenses within 24 hours`,
                `- CLI: nexus-prime license sync`,
            ];
            return { content: [{ type: 'text', text: lines.join('\n') }] };
        }
        case 'nexus_describe_tool': {
            const requestedTool = String(request.params.arguments?.tool_name ?? '');
            if (!requestedTool) {
                return { content: [{ type: 'text', text: 'tool_name is required.' }] };
            }
            const allToolDefs = hctx.getDecoratedToolDefinitions(hctx.getToolProfile());
            const found = allToolDefs.find(t => t.name === requestedTool);
            if (!found) {
                const available = allToolDefs.map(t => t.name).join(', ');
                return { content: [{ type: 'text', text: `Tool "${requestedTool}" not found. Available: ${available}` }] };
            }
            return {
                content: [{
                        type: 'text',
                        text: `## ${found.name}\n\n${found.description}\n\n**Schema:**\n\`\`\`json\n${JSON.stringify(found.inputSchema, null, 2)}\n\`\`\``,
                    }],
            };
        }
        case 'nexus_search': {
            const query = String(request.params.arguments?.query ?? '');
            const limit = Number(request.params.arguments?.limit ?? 20);
            const useSparse = Boolean(request.params.arguments?.sparse);
            if (!query.trim()) {
                return { content: [{ type: 'text', text: 'Search query is required.' }] };
            }
            const ngramIndex = hctx.getRepoNgramIndex(request.params.arguments ?? {});
            const { results, tokensSaved } = ngramIndex.searchWithStats(query, limit);
            if (results.length === 0) {
                return { content: [{ type: 'text', text: `No results found for "${query}".` }] };
            }
            const sparseResults = useSparse ? ngramIndex.searchSparse(query, limit) : null;
            const displayResults = sparseResults ?? results;
            const lines = displayResults.map((r, i) => `${i + 1}. ${r.docId} (score: ${r.score})`);
            const stats = ngramIndex.getSearchStats();
            const savingsLine = `\n📊 Token savings: ~${tokensSaved.toLocaleString()} tokens saved vs reading all ${results.length} matched files.\n` +
                `   Lifetime search savings: ${stats.totalTokensSaved.toLocaleString()} tokens across ${stats.totalQueries} queries.`;
            nexusEventBus.emit('tokens.searchSaved', {
                query: query.slice(0, 100),
                resultCount: displayResults.length,
                tokensSaved,
                source: 'nexus_search',
            });
            return {
                content: [{
                        type: 'text',
                        text: `Search results for "${query}" (${displayResults.length} matches):\n\n${lines.join('\n')}${savingsLine}`,
                    }],
            };
        }
        case 'nexus_token_report': {
            const scope = String(request.params.arguments?.scope ?? 'lifetime');
            const limit = Number(request.params.arguments?.limit ?? 10);
            const engine = new TokenAnalyticsEngine(hctx.nexusRef.memory);
            if (scope === 'recent') {
                const history = engine.getSessionHistory(limit);
                return {
                    content: [{
                            type: 'text',
                            text: history.length > 0
                                ? `📊 Recent Sessions Token Analytics:\n\n${history.map(s => `Session ID: ${s.sessionId}\n- Events: ${s.events}\n- Tokens Optimally Saved: ${s.tokensSaved.toLocaleString()} (x${s.compressionRatio.toFixed(2)} compression)\n- USD Saved: $${s.usdValueSaved.toFixed(4)}`).join('\n\n')}`
                                : 'No recent sessions found in token ledger.'
                        }]
                };
            }
            else {
                const report = engine.getLifetimeReport();
                return {
                    content: [{
                            type: 'text',
                            text: `📊 Lifetime Token Analytics:\n\n- Total Sessions: ${report.totalSessions}\n- Total MCP Events: ${report.totalEvents}\n- Tokens Optimally Saved: ${report.totalTokensSaved.toLocaleString()} (overall x${report.overallCompressionRatio.toFixed(2)} compression)\n- USD Saved: $${report.totalUsdSaved.toFixed(4)}`
                        }]
                };
            }
        }
        case 'nexus_session_search': {
            const query = String(request.params.arguments?.query ?? '');
            const result = hctx.nexusRef.searchSessionHistory(query, {
                limit: request.params.arguments?.limit == null ? undefined : Number(request.params.arguments.limit),
                minScore: request.params.arguments?.minScore == null ? undefined : Number(request.params.arguments.minScore),
                sessionsDir: request.params.arguments?.sessionsDir ? String(request.params.arguments.sessionsDir) : undefined,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            `Session search ready for "${query}".`,
                            formatBullets([
                                `Hits: ${result.length}`,
                                `Top session: ${result[0]?.session.sessionId || 'none'}`,
                            ]),
                            formatJsonDetails('Structured details', result),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_channel_map_thread': {
            const result = hctx.nexusRef.mapChannelThread({
                provider: String(request.params.arguments?.provider ?? ''),
                conversationId: String(request.params.arguments?.conversationId ?? ''),
                threadId: request.params.arguments?.threadId ? String(request.params.arguments.threadId) : undefined,
                messageId: request.params.arguments?.messageId ? String(request.params.arguments.messageId) : undefined,
                parentMessageId: request.params.arguments?.parentMessageId ? String(request.params.arguments.parentMessageId) : undefined,
                workspaceId: request.params.arguments?.workspaceId ? String(request.params.arguments.workspaceId) : undefined,
                target: {
                    kind: String(request.params.arguments?.targetKind ?? 'session'),
                    id: String(request.params.arguments?.targetId ?? ''),
                },
                sourceUrl: request.params.arguments?.sourceUrl ? String(request.params.arguments.sourceUrl) : undefined,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Channel thread mapped.',
                            formatBullets([
                                `Provider: ${result.provider}`,
                                `Target: ${result.target.kind}:${result.target.id}`,
                                `Thread key: ${result.threadKey}`,
                            ]),
                            formatJsonDetails('Structured details', result),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_channel_artifact_envelope': {
            const result = hctx.nexusRef.createChannelArtifactEnvelope({
                provider: String(request.params.arguments?.provider ?? ''),
                thread: request.params.arguments?.thread,
                artifactType: String(request.params.arguments?.artifactType ?? ''),
                artifactId: request.params.arguments?.artifactId ? String(request.params.arguments.artifactId) : undefined,
                title: String(request.params.arguments?.title ?? ''),
                summary: String(request.params.arguments?.summary ?? ''),
                body: request.params.arguments?.body ? String(request.params.arguments.body) : undefined,
                attachments: Array.isArray(request.params.arguments?.attachments)
                    ? request.params.arguments.attachments.map((attachment) => ({
                        name: String(attachment.name ?? ''),
                        kind: String(attachment.kind ?? 'file'),
                        content: attachment.content == null ? undefined : String(attachment.content),
                        path: attachment.path == null ? undefined : String(attachment.path),
                        mimeType: attachment.mimeType == null ? undefined : String(attachment.mimeType),
                        sizeBytes: attachment.sizeBytes == null ? undefined : Number(attachment.sizeBytes),
                    }))
                    : undefined,
                metadata: request.params.arguments?.metadata,
            });
            return {
                content: [{
                        type: 'text',
                        text: [
                            'Channel artifact envelope ready.',
                            formatBullets([
                                `Provider: ${result.provider}`,
                                `Artifact: ${result.artifactType}`,
                                `Attachments: ${result.attachments.length}`,
                            ]),
                            formatJsonDetails('Structured details', result),
                        ].join('\n\n'),
                    }],
            };
        }
        case 'nexus_federation_status': {
            const snapshot = hctx.getRuntime().getNetworkStatus();
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify(snapshot, null, 2),
                    }],
            };
        }
        case 'nexus_user_workflow_trace': {
            const runId = String(request.params.arguments?.runId ?? '');
            const fmt = String(request.params.arguments?.format ?? 'text');
            const trace = await hctx.getRuntime().getUserWorkflowTrace?.(runId);
            if (!trace) {
                return { content: [{ type: 'text', text: `User workflow trace not found: ${runId}` }] };
            }
            if (fmt === 'json') {
                return { content: [{ type: 'text', text: JSON.stringify(trace, null, 2) }] };
            }
            return {
                content: [{
                        type: 'text',
                        text: [
                            summarizeUserWorkflowTrace(trace),
                            '',
                            formatBullets([
                                `Run: ${trace.runId}`,
                                `Goal: ${truncateText(trace.goal, 120)}`,
                                `Actions: ${trace.userJourney.actions.length ? trace.userJourney.actions.slice(0, 5).join(' | ') : 'none recorded'}`,
                                `Files: ${trace.userJourney.selectedFiles.length ? trace.userJourney.selectedFiles.slice(0, 5).join(', ') : 'none selected'}`,
                                `Agents: ${trace.userJourney.selectedSpecialists.length ? trace.userJourney.selectedSpecialists.slice(0, 5).join(', ') : 'none selected'}`,
                                `Signals: ${trace.signals.length ? trace.signals.map(signal => `${signal.severity}:${signal.code}`).slice(0, 8).join(', ') : 'none'}`,
                            ]),
                            trace.signals.length
                                ? `Failure signals\n${formatBullets(trace.signals.map(signal => `${signal.code}: ${signal.summary}`))}`
                                : '',
                            trace.nextActions.length
                                ? `Next actions\n${formatBullets(trace.nextActions)}`
                                : '',
                        ].filter(Boolean).join('\n\n'),
                    }],
            };
        }
        case 'nexus_run_status': {
            const runId = String(request.params.arguments?.runId ?? '');
            const fmt = String(request.params.arguments?.format ?? 'text');
            // Check async gate first (fast in-memory jobs from withAsyncGate)
            const asyncJob = getAsyncGate().getJob(runId);
            if (asyncJob) {
                if (!asyncJob.lifecycleReportedAt
                    && (asyncJob.status === 'completed' || asyncJob.status === 'failed')) {
                    if (asyncJob.status === 'completed') {
                        hctx.telemetry.observeSuccessfulToolCall(asyncJob.tool, asyncJob.args ?? {});
                    }
                    const shouldPersistSuccess = [
                        'nexus_orchestrate',
                        'nexus_plan_execution',
                        'nexus_session_dna',
                        'nexus_ghost_pass',
                        'nexus_mindkit_check',
                    ].includes(asyncJob.tool);
                    try {
                        if (asyncJob.tool !== 'nexus_store_memory' && (asyncJob.status === 'failed' || shouldPersistSuccess)) {
                            const workspace = hctx.getWorkspace(asyncJob.args ?? {});
                            const repoName = workspace.repoName || path.basename(workspace.repoRoot || '');
                            const summary = asyncJob.status === 'completed'
                                ? `MCP ${asyncJob.tool} completed asynchronously. ${buildAutoMemorySummary(asyncJob.tool, asyncJob.args ?? {})}`
                                : `MCP ${asyncJob.tool} failed asynchronously: ${asyncJob.error ?? 'unknown failure'}. ${buildAutoMemorySummary(asyncJob.tool, asyncJob.args ?? {})}`;
                            hctx.nexusRef.storeMemory(summary.slice(0, 1200), asyncJob.status === 'completed' ? 0.55 : 0.72, [
                                '#mcp-result',
                                '#auto',
                                `#tool:${asyncJob.tool}`,
                                ...(repoName ? [`repo:${repoName}`, `#repo:${repoName}`] : []),
                                ...(asyncJob.status === 'completed' ? ['#workspace'] : ['#failure-mode', '#runtime-result', '#inbox']),
                            ]);
                        }
                    }
                    catch { /* best-effort lifecycle memory */ }
                    getAsyncGate().markLifecycleReported(runId);
                }
                if (fmt === 'nxl')
                    return nxlResult(asyncJob);
                return getAsyncGate().formatStatus(runId);
            }
            // Check orchestration store (durable — survives restart, richer stage info)
            try {
                const orchRun = getOrchRun(runId);
                if (orchRun) {
                    if (fmt === 'nxl')
                        return nxlResult(orchRun);
                    const elapsed = Date.now() - orchRun.startedAt;
                    const body = orchRun.status === 'completed'
                        ? `✅ Run ${runId} completed\n  Goal: ${orchRun.goal}\n  Stage: ${orchRun.stage}\n  Result: ${orchRun.resultSummary ?? '(no summary)'}`
                        : orchRun.status === 'failed'
                            ? `❌ Run ${runId} failed\n  Goal: ${orchRun.goal}\n  Error: ${orchRun.error ?? 'unknown'}`
                            : [
                                `⏳ Run ${runId}`,
                                `  Goal:     ${orchRun.goal.slice(0, 80)}`,
                                `  Status:   ${orchRun.status}`,
                                `  Stage:    ${orchRun.stage}`,
                                `  Progress: ${orchRun.progress}%`,
                                `  Elapsed:  ${Math.round(elapsed / 100) / 10}s`,
                                '',
                                'Poll again with nexus_run_status(runId) in a few seconds.',
                            ].join('\n');
                    return { content: [{ type: 'text', text: body }] };
                }
            }
            catch { /* store not available — fall through */ }
            // Fall through to phantom ExecutionRun (worktree-based runs)
            const run = await hctx.getRuntime().getRun(runId);
            if (!run) {
                return { content: [{ type: 'text', text: `❌ Run not found: ${runId}` }] };
            }
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({
                            runId: run.runId,
                            state: run.state,
                            result: run.result,
                            artifactsPath: run.artifactsPath,
                            workers: run.workerResults.length,
                            verifiedWorkers: run.workerResults.filter((worker) => worker.verified).length,
                            workflows: run.activeWorkflows.map((workflow) => workflow.name),
                            hooks: run.activeHooks.map((hook) => hook.name),
                            automations: run.activeAutomations.map((automation) => automation.name),
                            planner: run.plannerResult,
                            promotions: run.promotionDecisions,
                            shield: run.shieldDecisions,
                            memoryChecks: run.memoryChecks,
                            federation: run.federationState,
                            backends: run.selectedBackends,
                        }, null, 2),
                    }],
            };
        }
    }
    return undefined;
}
