import { resolvePrivateHostFetchOptions } from './http-policy.js';
import { jsonErrorResponse } from './error-response.js';
export function createDaemonMediaRouteHandlers(context) {
    return {
        getVoiceStatus: async () => Response.json(await context.voiceService.getStatus(Boolean(context.configManager.get('ui.voiceEnabled')))),
        getVoiceProviders: async () => Response.json({
            providers: await context.voiceService.getStatus(Boolean(context.configManager.get('ui.voiceEnabled'))).then((status) => status.providers),
        }),
        getVoiceVoices: async (url) => Response.json({ voices: await context.voiceService.listVoices(url.searchParams.get('providerId') ?? undefined) }),
        postVoiceTts: async (request) => handleVoiceTts(context, request),
        postVoiceStt: async (request) => handleVoiceStt(context, request),
        postVoiceRealtimeSession: async (request) => handleVoiceRealtimeSession(context, request),
        getWebSearchProviders: async () => Response.json({ providers: await context.webSearchService.getStatus().then((status) => status.providers) }),
        postWebSearch: async (request) => handleWebSearch(context, request),
        getArtifacts: () => Response.json({ artifacts: context.artifactStore.list() }),
        postArtifact: async (request) => handleArtifactCreate(context, request),
        getArtifact: (artifactId) => {
            const artifact = context.artifactStore.get(artifactId);
            return artifact
                ? Response.json({ artifact })
                : Response.json({ error: 'Unknown artifact' }, { status: 404 });
        },
        getArtifactContent: async (artifactId, request) => handleArtifactContent(context, artifactId, request),
        getMediaProviders: async () => Response.json({ providers: await context.mediaProviders.status() }),
        postMediaAnalyze: async (request) => handleMediaAnalyze(context, request),
        postMediaTransform: async (request) => handleMediaTransform(context, request),
        postMediaGenerate: async (request) => handleMediaGenerate(context, request),
        getMultimodalStatus: async () => Response.json(await context.multimodalService.getStatus()),
        getMultimodalProviders: async () => Response.json({ providers: await context.multimodalService.listProviders() }),
        postMultimodalAnalyze: async (request) => handleMultimodalAnalyze(context, request),
        postMultimodalPacket: async (request) => handleMultimodalPacket(context, request),
        postMultimodalWriteback: async (request) => handleMultimodalWriteback(context, request),
    };
}
async function handleVoiceTts(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const text = typeof body.text === 'string' ? body.text : '';
    if (!text.trim())
        return Response.json({ error: 'Missing text' }, { status: 400 });
    try {
        const result = await context.voiceService.synthesize(typeof body.providerId === 'string' ? body.providerId : undefined, {
            text,
            voiceId: typeof body.voiceId === 'string' ? body.voiceId : undefined,
            modelId: typeof body.modelId === 'string' ? body.modelId : undefined,
            format: typeof body.format === 'string' ? body.format : undefined,
            speed: typeof body.speed === 'number' ? body.speed : undefined,
            metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
        });
        return Response.json(result);
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 404 });
    }
}
async function handleVoiceStt(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    if (typeof body.audio !== 'object' || body.audio === null) {
        return Response.json({ error: 'Missing audio artifact' }, { status: 400 });
    }
    try {
        const result = await context.voiceService.transcribe(typeof body.providerId === 'string' ? body.providerId : undefined, {
            audio: body.audio,
            language: typeof body.language === 'string' ? body.language : undefined,
            modelId: typeof body.modelId === 'string' ? body.modelId : undefined,
            prompt: typeof body.prompt === 'string' ? body.prompt : undefined,
            metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
        });
        return Response.json(result);
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 404 });
    }
}
async function handleVoiceRealtimeSession(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    try {
        const result = await context.voiceService.openRealtimeSession(typeof body.providerId === 'string' ? body.providerId : undefined, {
            modelId: typeof body.modelId === 'string' ? body.modelId : undefined,
            voiceId: typeof body.voiceId === 'string' ? body.voiceId : undefined,
            inputFormat: typeof body.inputFormat === 'string' ? body.inputFormat : undefined,
            outputFormat: typeof body.outputFormat === 'string' ? body.outputFormat : undefined,
            instructions: typeof body.instructions === 'string' ? body.instructions : undefined,
            metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
        });
        return Response.json(result, { status: 201 });
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 404 });
    }
}
async function handleMediaAnalyze(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const provider = context.mediaProviders.findProvider('understand', typeof body.providerId === 'string' ? body.providerId : undefined);
    if (!provider?.analyze)
        return Response.json({ error: 'No media analysis provider is registered' }, { status: 404 });
    const artifact = typeof body.artifact === 'object' && body.artifact !== null
        ? body.artifact
        : typeof body.artifactId === 'string' && body.artifactId.trim().length > 0
            ? {
                artifactId: body.artifactId.trim(),
                mimeType: 'application/octet-stream',
                metadata: {},
            }
            : null;
    if (!artifact) {
        return Response.json({ error: 'Missing media artifact' }, { status: 400 });
    }
    return Response.json(await provider.analyze({
        artifact,
        prompt: typeof body.prompt === 'string' ? body.prompt : undefined,
        modelId: typeof body.modelId === 'string' ? body.modelId : undefined,
        metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
    }));
}
async function handleArtifactCreate(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const privateHostFetchOptions = resolvePrivateHostFetchOptions(body.allowPrivateHosts, {
        configManager: context.configManager,
        req,
        requireElevatedAccess: (request) => context.requireAdmin(request),
    });
    if (privateHostFetchOptions instanceof Response)
        return privateHostFetchOptions;
    try {
        const artifact = await context.artifactStore.create({
            ...(typeof body.kind === 'string' ? { kind: body.kind } : {}),
            ...(typeof body.mimeType === 'string' ? { mimeType: body.mimeType } : {}),
            ...(typeof body.filename === 'string' ? { filename: body.filename } : {}),
            ...(typeof body.dataBase64 === 'string' ? { dataBase64: body.dataBase64 } : {}),
            ...(typeof body.text === 'string' ? { text: body.text } : {}),
            ...(typeof body.path === 'string' ? { path: body.path } : {}),
            ...(typeof body.uri === 'string' ? { uri: body.uri } : {}),
            ...privateHostFetchOptions,
            ...(typeof body.retentionMs === 'number' ? { retentionMs: body.retentionMs } : {}),
            ...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
        });
        return Response.json({ artifact }, { status: 201 });
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 400 });
    }
}
async function handleArtifactContent(context, artifactId, req) {
    try {
        const { record, buffer } = await context.artifactStore.readContent(artifactId);
        const bytes = buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
        const headers = new Headers({
            'Content-Type': record.mimeType,
            'Content-Length': String(bytes.byteLength),
            'Cache-Control': 'private, max-age=60',
        });
        const download = new URL(req.url).searchParams.get('download');
        if (record.filename && download !== '0') {
            headers.set('Content-Disposition', `attachment; filename="${record.filename.replace(/"/g, '\\"')}"`);
        }
        return new Response(bytes, { status: 200, headers });
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 404 });
    }
}
async function handleWebSearch(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const query = typeof body.query === 'string' ? body.query.trim() : '';
    if (!query)
        return Response.json({ error: 'Missing query' }, { status: 400 });
    try {
        return Response.json(await context.webSearchService.search({
            query,
            ...(typeof body.providerId === 'string' ? { providerId: body.providerId } : {}),
            ...(typeof body.maxResults === 'number' ? { maxResults: body.maxResults } : {}),
            ...(typeof body.verbosity === 'string' ? { verbosity: body.verbosity } : {}),
            ...(typeof body.region === 'string' ? { region: body.region } : {}),
            ...(typeof body.safeSearch === 'string' ? { safeSearch: body.safeSearch } : {}),
            ...(typeof body.timeRange === 'string' ? { timeRange: body.timeRange } : {}),
            ...(typeof body.includeInstantAnswer === 'boolean' ? { includeInstantAnswer: body.includeInstantAnswer } : {}),
            ...(typeof body.includeEvidence === 'boolean' ? { includeEvidence: body.includeEvidence } : {}),
            ...(typeof body.evidenceTopN === 'number' ? { evidenceTopN: body.evidenceTopN } : {}),
            ...(typeof body.evidenceExtract === 'string' ? { evidenceExtract: body.evidenceExtract } : {}),
        }));
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 400 });
    }
}
async function handleMediaTransform(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const provider = context.mediaProviders.findProvider('transform', typeof body.providerId === 'string' ? body.providerId : undefined);
    if (!provider?.transform)
        return Response.json({ error: 'No media transform provider is registered' }, { status: 404 });
    if (typeof body.artifact !== 'object' || body.artifact === null) {
        return Response.json({ error: 'Missing media artifact' }, { status: 400 });
    }
    const operation = typeof body.operation === 'string' ? body.operation : '';
    if (!operation)
        return Response.json({ error: 'Missing media transform operation' }, { status: 400 });
    return Response.json(await provider.transform({
        artifact: body.artifact,
        operation,
        outputMimeType: typeof body.outputMimeType === 'string' ? body.outputMimeType : undefined,
        options: typeof body.options === 'object' && body.options !== null ? body.options : {},
        metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
    }));
}
async function handleMediaGenerate(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const provider = context.mediaProviders.findProvider('generate', typeof body.providerId === 'string' ? body.providerId : undefined);
    if (!provider?.generate)
        return Response.json({ error: 'No media generation provider is registered' }, { status: 404 });
    const prompt = typeof body.prompt === 'string' ? body.prompt : '';
    if (!prompt.trim())
        return Response.json({ error: 'Missing media generation prompt' }, { status: 400 });
    return Response.json(await provider.generate({
        prompt,
        outputMimeType: typeof body.outputMimeType === 'string' ? body.outputMimeType : undefined,
        modelId: typeof body.modelId === 'string' ? body.modelId : undefined,
        options: typeof body.options === 'object' && body.options !== null ? body.options : {},
        metadata: typeof body.metadata === 'object' && body.metadata !== null ? body.metadata : {},
    }));
}
async function handleMultimodalAnalyze(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    const requestedArtifact = typeof body.artifact === 'object' && body.artifact !== null
        ? body.artifact
        : null;
    const privateHostFetchOptions = resolvePrivateHostFetchOptions(body.allowPrivateHosts === true || requestedArtifact?.allowPrivateHosts === true, {
        configManager: context.configManager,
        req,
        requireElevatedAccess: (request) => context.requireAdmin(request),
    });
    if (privateHostFetchOptions instanceof Response)
        return privateHostFetchOptions;
    try {
        const analysis = await context.multimodalService.analyze({
            ...(typeof body.artifactId === 'string' ? { artifactId: body.artifactId } : {}),
            ...(requestedArtifact ? {
                artifact: {
                    ...requestedArtifact,
                    ...privateHostFetchOptions,
                },
            } : {}),
            ...(typeof body.prompt === 'string' ? { prompt: body.prompt } : {}),
            ...(typeof body.imageProviderId === 'string' ? { imageProviderId: body.imageProviderId } : {}),
            ...(typeof body.audioProviderId === 'string' ? { audioProviderId: body.audioProviderId } : {}),
            ...(typeof body.modelId === 'string' ? { modelId: body.modelId } : {}),
            ...(typeof body.language === 'string' ? { language: body.language } : {}),
            ...(typeof body.detail === 'string' ? { detail: body.detail } : {}),
            ...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
        });
        const includePacket = body.includePacket === true;
        const writeback = body.writeback === true || (typeof body.writeback === 'object' && body.writeback !== null);
        const writebackBody = typeof body.writeback === 'object' && body.writeback !== null
            ? body.writeback
            : null;
        const packet = includePacket
            ? context.multimodalService.buildPacket(analysis, typeof body.detail === 'string' ? body.detail : 'standard')
            : undefined;
        const writebackResult = writeback
            ? await context.multimodalService.writeBackAnalysis(analysis, {
                ...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
                ...(typeof writebackBody?.title === 'string' ? { title: writebackBody.title } : {}),
                ...(Array.isArray(writebackBody?.tags) ? { tags: writebackBody.tags.filter((entry) => typeof entry === 'string') } : {}),
                ...(typeof writebackBody?.folderPath === 'string' ? { folderPath: writebackBody.folderPath } : {}),
                ...(typeof writebackBody?.metadata === 'object' && writebackBody.metadata !== null ? { metadata: writebackBody.metadata } : {}),
            })
            : undefined;
        return Response.json({
            analysis,
            ...(packet ? { packet } : {}),
            ...(writebackResult ? { writeback: writebackResult } : {}),
        }, { status: 201 });
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 400 });
    }
}
async function handleMultimodalPacket(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    if (typeof body.analysis !== 'object' || body.analysis === null) {
        return Response.json({ error: 'Missing analysis payload' }, { status: 400 });
    }
    const detail = typeof body.detail === 'string' ? body.detail : 'standard';
    const budgetLimit = typeof body.budgetLimit === 'number' ? body.budgetLimit : undefined;
    return Response.json({
        packet: context.multimodalService.buildPacket(body.analysis, detail, budgetLimit),
    });
}
async function handleMultimodalWriteback(context, req) {
    const body = await context.parseJsonBody(req);
    if (body instanceof Response)
        return body;
    if (typeof body.analysis !== 'object' || body.analysis === null) {
        return Response.json({ error: 'Missing analysis payload' }, { status: 400 });
    }
    try {
        const writeback = await context.multimodalService.writeBackAnalysis(body.analysis, {
            ...(typeof body.sessionId === 'string' ? { sessionId: body.sessionId } : {}),
            ...(typeof body.title === 'string' ? { title: body.title } : {}),
            ...(Array.isArray(body.tags) ? { tags: body.tags.filter((entry) => typeof entry === 'string') } : {}),
            ...(typeof body.folderPath === 'string' ? { folderPath: body.folderPath } : {}),
            ...(typeof body.metadata === 'object' && body.metadata !== null ? { metadata: body.metadata } : {}),
        });
        return Response.json({ writeback }, { status: 201 });
    }
    catch (error) {
        return jsonErrorResponse(error, { status: 400 });
    }
}
