/**
 * Shared types for the MCP adapter split (Phase 3).
 *
 * Extracted from mcp.ts to break the 5000-LOC monolith into manageable files.
 * This module owns the SessionTelemetry tracker and the McpHandlerCtx dependency
 * injection interface that all handler files receive.
 */
// ─── SessionTelemetry (moved from mcp.ts) ─────────────────────────────────────
/** Session-level telemetry tracker. Moved to types.ts so handler files can
 *  reference the class without a circular import back into mcp.ts. */
export class SessionTelemetry {
    startTime = Date.now();
    callCount = 0;
    tokensOptimized = 0;
    memoriesStored = 0;
    memoriesRecalled = 0;
    lifecyclePhase = 'pre-bootstrap';
    optimizeTokensCalled = false;
    mindkitCheckCalled = false;
    storeMemoryCalledPostOrchestrate = false;
    sessionDnaCalled = false;
    fileReadIntentCount = 0;
    callsSinceOrchestrate = 0;
    fileIntentPaths = new Set();
    tokenAutoApplied = false;
    stickyTokenOptimization = false;
    tokenOptimizationPending = false;
    orchestrationPending = false;
    bootstrapped = false;
    bootstrapCallCount = 0;
    recordCall() {
        this.callCount++;
        if (this.isPostOrchestratePhase()) {
            this.callsSinceOrchestrate++;
        }
    }
    recordTokens(saved) { this.tokensOptimized += saved; }
    recordStore() { this.memoriesStored++; }
    recordRecall(count) { this.memoriesRecalled += count; }
    snapshot() {
        return {
            callCount: this.callCount,
            tokensOptimized: this.tokensOptimized,
            memoriesStored: this.memoriesStored,
            memoriesRecalled: this.memoriesRecalled,
            lifecyclePhase: this.lifecyclePhase,
            optimizeTokensCalled: this.optimizeTokensCalled,
            mindkitCheckCalled: this.mindkitCheckCalled,
            storeMemoryCalledPostOrchestrate: this.storeMemoryCalledPostOrchestrate,
            sessionDnaCalled: this.sessionDnaCalled,
            fileReadIntentCount: this.fileReadIntentCount,
            callsSinceOrchestrate: this.callsSinceOrchestrate,
            tokenAutoApplied: this.tokenAutoApplied,
            tokenOptimizationPending: this.tokenOptimizationPending,
            orchestrationPending: this.orchestrationPending,
        };
    }
    elapsedMs() {
        return Date.now() - this.startTime;
    }
    advancePhase(nextPhase) {
        if (this.lifecyclePhase === nextPhase)
            return;
        this.lifecyclePhase = nextPhase;
        if (nextPhase === 'bootstrapped' || nextPhase === 'orchestrated') {
            this.resetFileIntentTracking();
            if (this.stickyTokenOptimization) {
                this.optimizeTokensCalled = true;
                this.tokenAutoApplied = true;
                this.stickyTokenOptimization = false;
            }
            else {
                this.optimizeTokensCalled = false;
                this.tokenAutoApplied = false;
            }
            this.tokenOptimizationPending = false;
        }
        if (nextPhase === 'orchestrated') {
            this.orchestrationPending = false;
            this.mindkitCheckCalled = false;
            this.storeMemoryCalledPostOrchestrate = false;
            this.sessionDnaCalled = false;
            this.callsSinceOrchestrate = 0;
        }
    }
    observeSuccessfulToolCall(toolName, args) {
        if (toolName === 'nexus_session_bootstrap') {
            this.bootstrapped = true;
            this.advancePhase('bootstrapped');
            this.noteFileIntent(args.files);
            return;
        }
        if (toolName === 'nexus_orchestrate') {
            this.stickyTokenOptimization = true;
            this.advancePhase('orchestrated');
            this.optimizeTokensCalled = true;
            this.tokenAutoApplied = true;
            this.tokenOptimizationPending = false;
            this.noteFileIntent(args.files);
            return;
        }
        if (toolName === 'nexus_optimize_tokens') {
            this.optimizeTokensCalled = true;
            this.tokenOptimizationPending = false;
            if (this.lifecyclePhase === 'orchestrated')
                this.advancePhase('working');
            this.noteFileIntent(args.files);
            return;
        }
        if (toolName === 'nexus_mindkit_check') {
            this.mindkitCheckCalled = true;
            if (this.lifecyclePhase === 'orchestrated')
                this.advancePhase('working');
            this.noteFileIntent(args.filesToModify);
            return;
        }
        if (toolName === 'nexus_ghost_pass') {
            if (this.lifecyclePhase === 'orchestrated')
                this.advancePhase('working');
            this.noteFileIntent(args.files);
            return;
        }
        if (toolName === 'nexus_spawn_workers') {
            if (this.lifecyclePhase === 'bootstrapped' || this.lifecyclePhase === 'orchestrated') {
                this.advancePhase('working');
            }
            this.noteFileIntent(args.files);
            return;
        }
        if (toolName === 'nexus_store_memory') {
            if (this.isPostOrchestratePhase()) {
                this.storeMemoryCalledPostOrchestrate = true;
            }
            if (this.lifecyclePhase === 'orchestrated')
                this.advancePhase('working');
            return;
        }
        if (toolName === 'nexus_session_dna' && String(args.action ?? 'load') === 'generate') {
            this.sessionDnaCalled = true;
            this.advancePhase('closing');
            return;
        }
        if (this.lifecyclePhase === 'orchestrated') {
            this.advancePhase('working');
        }
    }
    observeQueuedToolCall(toolName, args) {
        if (toolName === 'nexus_orchestrate') {
            this.orchestrationPending = true;
            this.tokenOptimizationPending = true;
            this.optimizeTokensCalled = true;
            this.noteFileIntent(args.files);
            return;
        }
        if (toolName === 'nexus_optimize_tokens') {
            this.tokenOptimizationPending = true;
            this.optimizeTokensCalled = true;
            this.noteFileIntent(args.files);
        }
    }
    needsOptimizeTokens(currentToolName) {
        if (currentToolName === 'nexus_optimize_tokens')
            return false;
        if (currentToolName === 'nexus_mindkit_check')
            return false;
        if (this.lifecyclePhase === 'pre-bootstrap')
            return false;
        if (this.tokenAutoApplied)
            return false;
        if (this.tokenOptimizationPending)
            return false;
        return this.fileReadIntentCount >= 1 && !this.optimizeTokensCalled;
    }
    markTokenAutoApplied() {
        this.tokenAutoApplied = true;
        this.optimizeTokensCalled = true;
        this.stickyTokenOptimization = true;
        this.tokenOptimizationPending = false;
    }
    needsOrchestration(currentToolName) {
        if (currentToolName === 'nexus_orchestrate')
            return false;
        if (this.lifecyclePhase === 'pre-bootstrap')
            return false;
        if (this.lifecyclePhase === 'orchestrated' || this.lifecyclePhase === 'working' || this.lifecyclePhase === 'closing')
            return false;
        if (this.orchestrationPending)
            return false;
        return this.bootstrapped && this.lifecyclePhase === 'bootstrapped';
    }
    needsStoreMemory(currentToolName) {
        if (currentToolName === 'nexus_store_memory')
            return false;
        return this.isPostOrchestratePhase()
            && this.callsSinceOrchestrate >= 15
            && !this.storeMemoryCalledPostOrchestrate;
    }
    needsSessionDna(currentToolName) {
        if (currentToolName === 'nexus_session_dna')
            return false;
        return this.isPostOrchestratePhase() && !this.sessionDnaCalled;
    }
    notifyStore(priority, tags, memStats) {
        return `\nMemory telemetry: priority ${priority.toFixed(2)} · tags ${tags.join(', ') || 'none'} · cortex ${memStats.cortex} · zettel ${memStats.totalLinks}`;
    }
    notifyRecall(count, query, memStats) {
        return `\nMemory telemetry: ${count} recalled · query "${query.slice(0, 28)}" · hippocampus ${memStats.hippocampus}/200 · cortex ${memStats.cortex}`;
    }
    notifyTokens(task, savings, pct, fileCount) {
        return `\nToken telemetry: saved ${savings.toLocaleString()} (${pct}%) across ${fileCount} files · lifetime saved ${(this.tokensOptimized / 1000).toFixed(1)}k`;
    }
    /** Contextual planning nudges based on what just happened */
    planningNudge(event, context) {
        const nudges = [];
        switch (event) {
            case 'recall':
                if ((context.count ?? 0) > 3) {
                    nudges.push('Next: call nexus_optimize_tokens before reading the files mentioned.');
                }
                if ((context.count ?? 0) === 0) {
                    nudges.push('No memories found — fresh topic. Next: explore carefully and call nexus_store_memory with key findings.');
                }
                break;
            case 'optimize':
                if ((context.fullReads ?? 0) > 3) {
                    nudges.push('Next: call nexus_ghost_pass before modifying these files.');
                }
                break;
            case 'ghost_pass':
                if ((context.risks ?? 0) > 0) {
                    nudges.push('Risks detected. Next: call nexus_spawn_workers for parallel execution.');
                }
                break;
            case 'store':
                // Storing memory completes the lifecycle step; do not create a
                // self-referential "store again" loop.
                break;
            case 'mindkit_fail':
                nudges.push('Guardrail FAILED. Do NOT proceed. Re-scope the task or call nexus_ghost_pass for a safer approach.');
                break;
            case 'high_call_count':
                if (this.callsSinceOrchestrate >= 15 && !this.storeMemoryCalledPostOrchestrate) {
                    nudges.push('15+ post-orchestrate tool calls reached. Next: call nexus_store_memory with a session summary.');
                }
                break;
        }
        if (nudges.length === 0)
            return '';
        return `\n\nMANDATORY NEXT STEPS:\n${nudges.map((n) => `- ${n}`).join('\n')}\nDo NOT proceed without completing these steps.`;
    }
    format(memStats) {
        const uptime = Math.round((Date.now() - this.startTime) / 1000);
        const uptimeStr = uptime < 60 ? `${uptime}s` : `${Math.round(uptime / 60)}m`;
        const parts = [
            `${this.callCount} calls`,
            memStats ? `${memStats.totalLinks} Zettel links` : null,
            `phase ${this.lifecyclePhase}`,
        ].filter(Boolean);
        return `\nSession telemetry (${uptimeStr}): ${parts.join(' · ')}`;
    }
    noteFileIntent(rawPaths) {
        if (!Array.isArray(rawPaths))
            return;
        for (const rawPath of rawPaths) {
            const normalized = String(rawPath || '').trim();
            if (!normalized)
                continue;
            this.fileIntentPaths.add(normalized);
        }
        this.fileReadIntentCount = this.fileIntentPaths.size;
    }
    resetFileIntentTracking() {
        this.fileIntentPaths.clear();
        this.fileReadIntentCount = 0;
    }
    isPostOrchestratePhase() {
        return this.lifecyclePhase === 'orchestrated'
            || this.lifecyclePhase === 'working'
            || this.lifecyclePhase === 'closing';
    }
}
