import fs from 'fs/promises';
import path from 'path';
import { CONTEXT_LOG_FILE, DECISION_LOG_FILE, REQUEST_BRIEF_FILE, SELECTION_PLAN_FILE, } from '../../engines/orchestrator/decision-spine.js';
import { getSharedNgramIndex } from '../../engines/ngram-index.js';
import { getRun as getStoredRun, getSpans } from '../../engines/orchestrator/store.js';
import { getSharedTelemetry } from '../../engines/telemetry-remote.js';
import { getDashboardEventCards } from '../stream/sse-broker.js';
async function readJsonArtifact(run, filename, fallback) {
    if (!run?.artifactsPath)
        return fallback;
    try {
        return JSON.parse(await fs.readFile(path.join(run.artifactsPath, filename), 'utf8'));
    }
    catch {
        return fallback;
    }
}
async function readJsonlArtifact(run, filename, fallback) {
    if (!run?.artifactsPath)
        return fallback;
    try {
        const text = await fs.readFile(path.join(run.artifactsPath, filename), 'utf8');
        return text
            .split('\n')
            .map((line) => line.trim())
            .filter(Boolean)
            .map((line) => JSON.parse(line));
    }
    catch {
        return fallback;
    }
}
function storedRunDecisionSpine(run) {
    const spans = getSpans(run.runId);
    const contextLog = spans.length
        ? spans.map((span) => ({
            phase: span.name,
            actor: 'dashboard',
            reason: String(span.attrs?.summary ?? span.attrs?.state ?? span.name),
            createdAt: span.startedAt,
            contextRefs: [span.spanId],
            evidenceRefs: [
                span.attrs?.actualRunId ? `actual:${span.attrs.actualRunId}` : null,
                span.status === 'error' && span.attrs?.error ? `error:${span.attrs.error}` : null,
            ].filter(Boolean),
        }))
        : [{
                phase: run.stage ?? 'intake',
                actor: run.client ?? 'dashboard',
                reason: `${run.status ?? 'queued'} run: ${run.goal ?? run.runId}`,
                createdAt: run.updatedAt ?? run.startedAt ?? Date.now(),
                evidenceRefs: [run.runId],
            }];
    const decisionLog = [{
            verb: run.status === 'failed' ? 'blocked' : run.status === 'completed' ? 'completed' : 'queued',
            surface: 'dashboard',
            decision: run.status === 'failed'
                ? (run.error ?? 'Run failed')
                : run.status === 'completed'
                    ? (run.resultSummary ?? 'Run completed')
                    : `Run is ${run.stage ?? run.status ?? 'queued'}`,
            reason: run.goal ?? '',
            createdAt: run.completedAt ?? run.updatedAt ?? run.startedAt ?? Date.now(),
            beforeRef: run.runId,
            afterRef: run.status === 'completed' ? 'orchestration-store' : null,
        }];
    const requestBrief = {
        runId: run.runId,
        rawPrompt: run.goal,
        intent: 'orchestrate',
        risk: run.status === 'failed' ? 'needs-attention' : 'standard',
        source: run.client ?? 'dashboard',
        createdAt: run.startedAt,
    };
    const selectionPlan = {
        runId: run.runId,
        intent: 'orchestrate',
        selected: {
            files: [],
            skills: [],
            specialists: [],
            crews: [],
        },
        executionPolicy: {
            route: run.client ?? 'dashboard',
            stage: run.stage,
            progress: run.progress,
        },
    };
    return {
        runId: run.runId,
        artifactsPath: null,
        files: {
            requestBrief: REQUEST_BRIEF_FILE,
            selectionPlan: SELECTION_PLAN_FILE,
            contextLog: CONTEXT_LOG_FILE,
            decisionLog: DECISION_LOG_FILE,
        },
        artifacts: {
            requestBrief,
            selectionPlan,
            contextLog,
            decisionLog,
        },
        summary: {
            intent: requestBrief.intent,
            risk: requestBrief.risk,
            modelRoute: null,
            selected: selectionPlan.selected,
            contextEvents: contextLog.length,
            decisions: decisionLog.length,
            latestDecision: decisionLog[decisionLog.length - 1],
            source: 'orchestration-store',
        },
    };
}
export const handleEventRoutes = async (ctx, req, res, url) => {
    if (req.method === 'GET' && url.pathname === '/stream') {
        ctx.serveSse(req, res);
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/events') {
        const category = url.searchParams.get('category');
        const type = url.searchParams.get('type');
        const limit = parseInt(url.searchParams.get('limit') || '80', 10);
        const filtered = getDashboardEventCards()
            .filter((event) => !category || event.category === category)
            .filter((event) => !type || event.type === type);
        const actionFirst = [
            ...filtered.filter((event) => event.type === 'dashboard.action'),
            ...filtered.filter((event) => event.type !== 'dashboard.action'),
        ];
        const events = actionFirst.slice(0, Math.max(limit, 1));
        ctx.respondJson(res, events);
        return true;
    }
    const decisionSpineMatch = req.method === 'GET'
        ? /^\/api\/runs\/([^/]+)\/decision-spine$/.exec(url.pathname)
        : null;
    if (decisionSpineMatch) {
        const runId = decodeURIComponent(decisionSpineMatch[1]);
        const run = await ctx.getRuntime()?.getRun?.(runId);
        if (!run) {
            const stored = getStoredRun(runId);
            if (!stored) {
                ctx.respondJson(res, { error: 'decision-spine-not-found', runId }, 404);
                return true;
            }
            ctx.respondJson(res, storedRunDecisionSpine(stored));
            return true;
        }
        const [requestBrief, selectionPlan, contextLog, decisionLog] = await Promise.all([
            readJsonArtifact(run, REQUEST_BRIEF_FILE, run.requestBrief ?? null),
            readJsonArtifact(run, SELECTION_PLAN_FILE, run.selectionPlan ?? null),
            readJsonlArtifact(run, CONTEXT_LOG_FILE, Array.isArray(run.contextLog) ? run.contextLog : []),
            readJsonlArtifact(run, DECISION_LOG_FILE, Array.isArray(run.decisionLog) ? run.decisionLog : []),
        ]);
        ctx.respondJson(res, {
            runId,
            artifactsPath: run.artifactsPath ?? null,
            files: {
                requestBrief: REQUEST_BRIEF_FILE,
                selectionPlan: SELECTION_PLAN_FILE,
                contextLog: CONTEXT_LOG_FILE,
                decisionLog: DECISION_LOG_FILE,
            },
            artifacts: {
                requestBrief,
                selectionPlan,
                contextLog,
                decisionLog,
            },
            summary: {
                intent: requestBrief?.intent ?? selectionPlan?.intent ?? run.intent ?? null,
                risk: requestBrief?.risk ?? null,
                modelRoute: selectionPlan?.modelRoute ?? requestBrief?.modelPolicy ?? null,
                budgets: selectionPlan?.budgets ?? null,
                executionPolicy: selectionPlan?.executionPolicy ?? null,
                agentFlow: selectionPlan?.executionPolicy?.agentFlow ?? null,
                selected: selectionPlan?.selected ?? null,
                contextEvents: Array.isArray(contextLog) ? contextLog.length : 0,
                decisions: Array.isArray(decisionLog) ? decisionLog.length : 0,
                latestDecision: Array.isArray(decisionLog) && decisionLog.length
                    ? decisionLog[decisionLog.length - 1]
                    : null,
            },
        });
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/search/stats') {
        try {
            const ngramIndex = getSharedNgramIndex();
            ctx.respondJson(res, { ...ngramIndex.getSearchStats(), index: ngramIndex.getStats() });
        }
        catch (err) {
            ctx.respondJson(res, { error: err?.message ?? 'search stats unavailable' }, 500);
        }
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/search/recent') {
        try {
            const ngramIndex = getSharedNgramIndex();
            const stats = ngramIndex.getSearchStats();
            ctx.respondJson(res, { recentQueries: stats.recentQueries.slice(-20) });
        }
        catch (err) {
            ctx.respondJson(res, { error: err?.message ?? 'recent queries unavailable' }, 500);
        }
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/telemetry/status') {
        try {
            ctx.respondJson(res, getSharedTelemetry().getStats());
        }
        catch {
            ctx.respondJson(res, { installId: 'unknown', optedIn: false, queuedEvents: 0, remoteStatsConfigured: false }, 200);
        }
        return true;
    }
    if (req.method === 'GET' && (url.pathname === '/api/telemetry/remote' || url.pathname === '/api/telemetry/remote-stats')) {
        try {
            ctx.respondJson(res, await getSharedTelemetry().fetchRemoteStats());
        }
        catch {
            ctx.respondJson(res, { configured: false, totalInstalls: 0, activeInstalls7d: 0, totalSessions: 0, totalTokenSavings: 0, totalMemoriesCreated: 0, totalMemoriesRecalled: 0, installs: [] }, 200);
        }
        return true;
    }
    return false;
};
