import { randomUUID } from 'crypto';
import { TokenSupremacyEngine } from './token-supremacy.js';
import { createKVBridge } from './kv-bridge.js';
import { MetaLearner } from './meta-learner.js';
import { nxl } from './nxl-interpreter.js';
export class SQLiteMemoryBackend {
    memory;
    descriptor = {
        kind: 'sqlite-memory',
        mode: 'default',
        details: {
            supportsHyperbolicShadow: true,
            supportsTemporalShadow: true,
        },
    };
    constructor(memory) {
        this.memory = memory;
    }
    async recall(query, k = 5, filters) {
        return this.memory.recall(query, k, filters);
    }
    store(content, priority = 0.7, tags = [], parentId, depth = 0) {
        return this.memory.store(content, priority, tags, parentId, depth);
    }
    stats() {
        return this.memory.getStats();
    }
    async shadowRecall(query, k = 5, filters) {
        const recalled = await this.memory.recall(query, k, filters);
        return {
            query,
            strategy: 'temporal-hyperbolic-shadow',
            recalled,
            notes: [
                'Using SQLite memory backend as the source of truth.',
                'Temporal/hyperbolic ranking remains in shadow mode until promoted.',
            ],
        };
    }
}
export class TemporalHyperbolicMemoryBackend extends SQLiteMemoryBackend {
    descriptor = {
        kind: 'temporal-hyperbolic-memory',
        mode: 'experimental',
        details: {
            strategy: 'priority+recency+depth',
        },
    };
    async recall(query, k = 5, filters) {
        const snapshot = this.memory.snapshot?.(Math.max(k * 6, 24)) ?? [];
        if (snapshot.length === 0) {
            return super.recall(query, k, filters);
        }
        const queryTerms = query.toLowerCase().split(/\s+/).filter(Boolean);
        return snapshot
            .map((item) => ({
            item,
            score: rankTemporalHyperbolic(queryTerms, item),
        }))
            .sort((a, b) => b.score - a.score)
            .slice(0, k)
            .map(({ item }) => item.content);
    }
    async shadowRecall(query, k = 5, filters) {
        const promoted = await this.recall(query, k, filters);
        const baseline = await super.recall(query, k, filters);
        return {
            query,
            baseline,
            promoted,
            notes: [
                'Temporal/hyperbolic backend reranks by recency, priority, and hierarchy depth.',
                'Baseline SQLite recall is preserved for fallback and comparison.',
            ],
        };
    }
}
export class DeterministicCompressionBackend {
    descriptor = {
        kind: 'deterministic-token-supremacy',
        mode: 'default',
        details: {
            shadow: 'adaptive-kv-merge',
        },
    };
    tokenEngine;
    shadowBridge;
    constructor(tokenEngine, shadowBridge) {
        this.tokenEngine = tokenEngine ?? new TokenSupremacyEngine();
        this.shadowBridge = shadowBridge ?? createKVBridge({
            inferenceBackend: 'mock',
            endpoint: 'local-shadow',
            modelId: 'shadow-adaptive-kv-merge',
            agents: 3,
        });
    }
    async planFiles(task, files) {
        return this.tokenEngine.plan(task, files);
    }
    allocateWorkerBudget(workerIds, plan) {
        const budgets = new Map();
        const usable = Math.max(plan.totalEstimatedTokens, workerIds.length);
        const perWorker = Math.max(200, Math.floor(usable / Math.max(workerIds.length, 1)));
        workerIds.forEach(id => budgets.set(id, perWorker));
        return budgets;
    }
    async shadow(task, files) {
        const bridgeMetrics = this.shadowBridge.getMetrics();
        return {
            mode: 'shadow',
            bridgeMetrics,
            notes: [
                `Shadow compression evaluation for "${task.slice(0, 80)}"`,
                `Files considered: ${files.length}`,
                'Deterministic planning remains the default apply path.',
            ],
        };
    }
}
export class MetaCompressionBackend extends DeterministicCompressionBackend {
    descriptor = {
        kind: 'meta-compression',
        mode: 'experimental',
        details: {
            driver: 'meta-learner+kv-bridge',
        },
    };
    metaLearner = new MetaLearner();
    async planFiles(task, files) {
        const baseline = normalizeReadingPlan(await super.planFiles(task, files)).plan;
        const candidateFiles = baseline.files.slice(0, Math.min(6, baseline.files.length));
        const scores = candidateFiles.map((entry, index) => {
            const prediction = this.metaLearner.predict([[entry.estimatedTokens || 1]], task, index + 1, Math.max(candidateFiles.length, 1), [entry.estimatedTokens || 1, entry.file.sizeBytes || 1], [Math.max(1, Math.floor((entry.estimatedTokens || 1) / 2)), Math.max(1, Math.floor((entry.file.sizeBytes || 1) / 2))]);
            return {
                path: entry.file.path,
                shouldMerge: prediction.shouldMerge,
                t: prediction.t,
                gamma: prediction.gamma,
            };
        });
        const fullPaths = new Set(scores.filter((score) => score.shouldMerge || score.t > 0.55).map((score) => score.path));
        const adjustedFiles = baseline.files.map((entry) => {
            if (fullPaths.has(entry.file.path) && entry.action !== 'full') {
                return {
                    ...entry,
                    action: 'partial',
                    reason: `${entry.reason}; meta-compression retained more context`,
                };
            }
            return entry;
        });
        return {
            plan: {
                ...baseline,
                files: adjustedFiles,
            },
            notes: [
                `Meta-compression evaluated ${scores.length} candidate file chunks.`,
                'Deterministic plan remains available for fallback.',
            ],
        };
    }
    allocateWorkerBudget(workerIds, plan) {
        const budgets = new Map();
        const total = Math.max(plan.totalEstimatedTokens, workerIds.length * 200);
        workerIds.forEach((id, index) => {
            const weight = 1 + ((workerIds.length - index) / Math.max(workerIds.length, 1)) * 0.25;
            budgets.set(id, Math.max(200, Math.round((total / Math.max(workerIds.length, 1)) * weight)));
        });
        return budgets;
    }
    async shadow(task, files) {
        const base = await super.shadow(task, files);
        return {
            ...base,
            mode: 'experimental',
            notes: [...base.notes, 'Meta-compression can materially alter worker budgets and file routing.'],
        };
    }
}
export class DeterministicDSLCompilerBackend {
    interpreter;
    descriptor = {
        kind: 'deterministic-nxl-compiler',
        mode: 'default',
        details: {
            futureBackend: 'agentlang-neural',
        },
    };
    constructor(interpreter = nxl) {
        this.interpreter = interpreter;
    }
    compile(goal, rawScript, useCase) {
        const raw = rawScript ? this.interpreter.parse(rawScript) : {};
        const spec = this.interpreter.compileExecution(goal, raw, useCase);
        return {
            spec,
            raw,
            archetypes: this.interpreter.induceArmy(useCase || goal),
            notes: ['Deterministic NXL compilation selected.'],
        };
    }
}
export class ExperimentalAgentLangCompilerBackend extends DeterministicDSLCompilerBackend {
    descriptor = {
        kind: 'agentlang-neural-compiler',
        mode: 'experimental',
        details: {
            fallback: 'deterministic-nxl-compiler',
        },
    };
    compile(goal, rawScript, useCase) {
        const compiled = super.compile(goal, rawScript, useCase);
        const normalizedRoles = Array.from(new Set([...compiled.spec.roles, 'skill-maker', 'research-shadow']));
        return {
            ...compiled,
            spec: {
                ...compiled.spec,
                roles: normalizedRoles,
                backendMode: 'experimental',
                metadata: {
                    ...compiled.spec.metadata,
                    compilerPath: 'experimental-agentlang-neural',
                },
            },
            notes: [...(compiled.notes ?? []), 'Experimental AgentLang/neural compiler path selected.', 'Validation fallback remains deterministic.'],
        };
    }
}
export function buildRunId(prefix = 'run') {
    return `${prefix}_${randomUUID().slice(0, 8)}`;
}
export function normalizeReadingPlan(result) {
    return 'plan' in result ? result : { plan: result, notes: [] };
}
export function createRuntimeBackendRegistry(memory) {
    const deterministicCompression = new DeterministicCompressionBackend();
    const registry = {
        memory: new Map([
            ['sqlite-memory', new SQLiteMemoryBackend(memory)],
            ['temporal-hyperbolic-memory', new TemporalHyperbolicMemoryBackend(memory)],
        ]),
        compression: new Map([
            ['deterministic-token-supremacy', deterministicCompression],
            ['meta-compression', new MetaCompressionBackend()],
        ]),
        dsl: new Map([
            ['deterministic-nxl-compiler', new DeterministicDSLCompilerBackend()],
            ['agentlang-neural-compiler', new ExperimentalAgentLangCompilerBackend()],
        ]),
    };
    return registry;
}
export function resolveBackend(registry, requested, fallbackKey) {
    if (requested && registry.has(requested)) {
        const selected = registry.get(requested);
        const descriptor = selected.descriptor;
        return { selected, descriptor };
    }
    const selected = registry.get(fallbackKey);
    const descriptor = selected.descriptor;
    return {
        selected,
        descriptor,
        fallback: requested && requested !== fallbackKey ? fallbackKey : undefined,
    };
}
function rankTemporalHyperbolic(queryTerms, item) {
    const content = item.content.toLowerCase();
    const overlap = queryTerms.reduce((sum, term) => sum + (content.includes(term) ? 1 : 0), 0);
    const recency = Math.exp(-(Date.now() - item.timestamp) / (14 * 24 * 3600 * 1000));
    const depthBonus = 1 / (1 + Math.max(item.depth ?? 0, 0));
    return overlap * 0.45 + item.priority * 0.25 + recency * 0.2 + depthBonus * 0.1;
}
export const createSQLiteMemoryBackend = (memory) => new SQLiteMemoryBackend(memory);
export const createDeterministicCompressionBackend = (tokenEngine, shadowBridge) => new DeterministicCompressionBackend(tokenEngine, shadowBridge);
export const createDeterministicDSLCompilerBackend = (interpreter) => new DeterministicDSLCompilerBackend(interpreter);
