import { nexusEventBus } from '../../engines/event-bus.js';
import { serializeSpecialistsCatalog } from '../selectors/assets-selector.js';
import { listStarterSpecialists } from '../../engines/specialist-roster.js';
import { estimateSpecialistSortieCost } from '../../engines/specialist-cost-estimator.js';
export const handleAssetRoutes = async (ctx, req, res, url) => {
    const runtimeId = ctx.getRuntime()?.getRuntimeId?.() ?? 'default';
    if (req.method === 'GET' && url.pathname === '/api/feature-registry') {
        await ctx.respondCachedJson(res, 'feature-registry', 30_000, () => Promise.resolve(ctx.buildFeatureRegistry()));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/skills') {
        await ctx.respondCachedJson(res, `catalog:skills:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getRuntime()?.listSkills?.() ?? []));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/skills/distribution') {
        await ctx.respondCachedJson(res, `catalog:skill-distribution:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getSkillDistributionManifest()));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/workflows') {
        await ctx.respondCachedJson(res, `catalog:workflows:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getRuntime()?.listWorkflows?.() ?? []));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/hooks') {
        await ctx.respondCachedJson(res, `catalog:hooks:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getRuntime()?.listHooks?.() ?? []));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/automations') {
        await ctx.respondCachedJson(res, `catalog:automations:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getRuntime()?.listAutomations?.() ?? []));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/specialists') {
        const showAll = url.searchParams.get('all') === '1';
        const cacheKey = showAll
            ? `catalog:specialists-all:${runtimeId}`
            : `catalog:specialists-curated:${runtimeId}`;
        await ctx.respondCachedJson(res, cacheKey, 15_000, () => {
            const raw = showAll
                ? (ctx.getRuntime()?.listSpecialists?.() ?? [])
                : listStarterSpecialists();
            return Promise.resolve(serializeSpecialistsCatalog(raw).map((s) => ({
                ...s,
                pricing: estimateSpecialistSortieCost(s),
            })));
        });
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/specialists/curated') {
        await ctx.respondCachedJson(res, `catalog:specialists-curated:${runtimeId}`, 60_000, () => {
            const starters = listStarterSpecialists();
            return Promise.resolve(starters.map((s) => ({
                specialistId: s.specialistId,
                name: s.name,
                division: s.division,
                description: s.description,
                emoji: s.emoji ?? null,
                domains: s.domains ?? [],
                authority: s.authority,
                pricing: estimateSpecialistSortieCost(s),
            })));
        });
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/crews') {
        await ctx.respondCachedJson(res, `catalog:crews:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getRuntime()?.listCrews?.() ?? []));
        return true;
    }
    if (req.method === 'GET' && url.pathname === '/api/backends') {
        await ctx.respondCachedJson(res, `catalog:backends:${runtimeId}`, 15_000, () => Promise.resolve(ctx.getRuntime()?.getBackendCatalog?.() ?? {}));
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/skills/deploy') {
        const body = await ctx.readJsonBody(req);
        const deployed = ctx.getRuntime()?.deploySkill?.(String(body.skillId), body.scope);
        if (deployed) {
            nexusEventBus.emit('skill.deploy', {
                skillId: deployed.skillId,
                scope: deployed.scope,
                status: deployed.rolloutStatus,
            });
        }
        ctx.respondJson(res, deployed ?? { error: 'skill-not-found' }, deployed ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/skills/revoke') {
        const body = await ctx.readJsonBody(req);
        const revoked = ctx.getRuntime()?.revokeSkill?.(String(body.skillId));
        if (revoked) {
            nexusEventBus.emit('skill.revoke', {
                skillId: revoked.skillId,
                status: revoked.rolloutStatus,
            });
        }
        ctx.respondJson(res, revoked ?? { error: 'skill-not-found' }, revoked ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/skills/register') {
        const body = await ctx.readJsonBody(req);
        const runtime = ctx.getRuntime();
        if (!runtime) {
            ctx.respondJson(res, { error: 'runtime-unavailable' }, 503);
            return true;
        }
        try {
            const riskClass = (['read', 'orchestrate', 'mutate'].includes(body.riskClass) ? body.riskClass : 'orchestrate');
            const scope = (['session', 'worker', 'global'].includes(body.scope) ? body.scope : 'session');
            const skill = runtime.generateSkill({
                name: String(body.name || 'unnamed-skill'),
                instructions: String(body.instructions || ''),
                riskClass,
                scope,
            });
            nexusEventBus.emit('skill.register', {
                name: skill.name,
                id: skill.skillId,
            });
            ctx.respondJson(res, skill);
        }
        catch (err) {
            ctx.respondJson(res, { error: err.message || 'register-failed' }, 400);
        }
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/workflows/deploy') {
        const body = await ctx.readJsonBody(req);
        const deployed = ctx.getRuntime()?.deployWorkflow?.(String(body.workflowId), body.scope);
        if (deployed) {
            nexusEventBus.emit('workflow.deploy', {
                workflowId: deployed.workflowId,
                scope: deployed.scope,
                status: deployed.rolloutStatus,
            });
        }
        ctx.respondJson(res, deployed ?? { error: 'workflow-not-found' }, deployed ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/workflows/run') {
        const body = await ctx.readJsonBody(req);
        const runtime = ctx.getRuntime();
        if (!runtime) {
            ctx.respondJson(res, { error: 'runtime-unavailable' }, 503);
            return true;
        }
        try {
            const run = await runtime.runWorkflow(String(body.workflowId), body.goal ? String(body.goal) : undefined);
            nexusEventBus.emit('workflow.run', {
                workflowId: String(body.workflowId),
                runId: run.runId,
                status: run.state,
            });
            ctx.respondJson(res, run);
        }
        catch (error) {
            ctx.respondJson(res, { error: error instanceof Error ? error.message : 'workflow-run-failed' }, 400);
        }
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/hooks/deploy') {
        const body = await ctx.readJsonBody(req);
        const deployed = ctx.getRuntime()?.deployHook?.(String(body.hookId), body.scope);
        if (deployed) {
            nexusEventBus.emit('hook.deploy', {
                hookId: deployed.hookId,
                scope: deployed.scope,
                status: deployed.rolloutStatus,
            });
        }
        ctx.respondJson(res, deployed ?? { error: 'hook-not-found' }, deployed ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/hooks/revoke') {
        const body = await ctx.readJsonBody(req);
        const revoked = ctx.getRuntime()?.revokeHook?.(String(body.hookId));
        if (revoked) {
            nexusEventBus.emit('hook.revoke', {
                hookId: revoked.hookId,
                status: revoked.rolloutStatus,
            });
        }
        ctx.respondJson(res, revoked ?? { error: 'hook-not-found' }, revoked ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/automations/deploy') {
        const body = await ctx.readJsonBody(req);
        const deployed = ctx.getRuntime()?.deployAutomation?.(String(body.automationId), body.scope);
        if (deployed) {
            nexusEventBus.emit('automation.deploy', {
                automationId: deployed.automationId,
                scope: deployed.scope,
                status: deployed.rolloutStatus,
            });
        }
        ctx.respondJson(res, deployed ?? { error: 'automation-not-found' }, deployed ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/automations/revoke') {
        const body = await ctx.readJsonBody(req);
        const revoked = ctx.getRuntime()?.revokeAutomation?.(String(body.automationId));
        if (revoked) {
            nexusEventBus.emit('automation.revoke', {
                automationId: revoked.automationId,
                status: revoked.rolloutStatus,
            });
        }
        ctx.respondJson(res, revoked ?? { error: 'automation-not-found' }, revoked ? 200 : 404);
        return true;
    }
    if (req.method === 'POST' && url.pathname === '/api/automations/run') {
        const body = await ctx.readJsonBody(req);
        const runtime = ctx.getRuntime();
        if (!runtime) {
            ctx.respondJson(res, { error: 'runtime-unavailable' }, 503);
            return true;
        }
        const run = await runtime.runAutomation(String(body.automationId), body.goal ? String(body.goal) : undefined);
        nexusEventBus.emit('automation.run', {
            automationId: String(body.automationId),
            trigger: 'manual',
            queued: false,
        });
        ctx.respondJson(res, run, 201);
        return true;
    }
    return false;
};
