import { executeSummarize } from "../application/execute-summarize.js";
import { execFileTracked } from "../processes.js";
import { runWithProcessContext } from "../processes.js";
import { formatModelLabelForDisplay } from "../run/finish-line.js";
import { resolveAutoDaemonMode } from "./auto-mode.js";
import { emitMeta, emitSlidesDone, pushToSession, scheduleSessionCleanup, } from "./server-session.js";
import { createDaemonSummarizeEventAdapter, } from "./server-summarize-events.js";
import { buildDaemonSummaryMetrics } from "./summarize-presentation.js";
import { assertDaemonUrlFetchAllowed, createDaemonUrlFetchGuard } from "./url-fetch-guard.js";
function toApplicationRequest({ request, input, extractOnly = request.extractOnly, }) {
    const modelOverride = request.modelOverride && request.modelOverride.toLowerCase() !== "auto"
        ? request.modelOverride
        : null;
    return {
        input,
        modelOverride,
        promptOverride: request.promptOverride,
        lengthRaw: request.lengthRaw,
        languageRaw: request.languageRaw,
        format: request.format,
        overrides: request.overrides,
        extractOnly,
        slides: request.slidesSettings,
    };
}
function toApplicationRuntime({ runId, env, fetchImpl, urlFetchImpl, cache, mediaCache, }) {
    return {
        runId,
        env,
        fetch: fetchImpl,
        urlFetch: urlFetchImpl,
        execFile: execFileTracked,
        cache,
        mediaCache,
    };
}
export async function handleExtractOnlySummarizeRequest({ request, env, fetchImpl, urlFetchImpl, cacheState, mediaCache, }) {
    const requestCache = request.noCache
        ? { ...cacheState, mode: "bypass", store: null }
        : cacheState;
    const runId = crypto.randomUUID();
    return await runWithProcessContext({ runId, source: "extract" }, async () => {
        const result = await executeSummarize(toApplicationRequest({
            request,
            input: {
                kind: "url",
                url: request.pageUrl,
                title: request.title,
                maxCharacters: request.maxCharacters,
            },
            extractOnly: true,
        }), toApplicationRuntime({
            runId,
            env,
            fetchImpl,
            urlFetchImpl,
            cache: requestCache,
            mediaCache,
        }));
        if (result.kind !== "extraction") {
            throw new Error("Internal error: expected extraction result");
        }
        return { extracted: result.extracted, slides: result.slides };
    });
}
export function toExtractOnlySlidesPayload(slides) {
    if (!slides || slides.slides.length === 0)
        return null;
    return {
        sourceUrl: slides.sourceUrl,
        sourceId: slides.sourceId,
        sourceKind: slides.sourceKind,
        ocrAvailable: slides.ocrAvailable,
        slides: slides.slides.map((slide) => ({
            index: slide.index,
            timestamp: slide.timestamp,
            ocrText: slide.ocrText ?? null,
            ocrConfidence: slide.ocrConfidence ?? null,
        })),
    };
}
export async function executeSummarizeSession({ session, request, env, fetchImpl, urlFetchImpl, cacheState, mediaCache, port, onSessionEvent, requestLogger, includeContentLog, logStartedAt, logInput, logSlidesSettings, sessions, refreshSessions, }) {
    const { pageUrl, title, textContent, truncated, noCache, mode, maxCharacters, slidesSettings, hasText, } = request;
    const eventAdapter = createDaemonSummarizeEventAdapter({
        session,
        pageUrl,
        slidesRequested: Boolean(slidesSettings),
        port,
        onSessionEvent,
        includeContentLog,
        requestLogger,
        logSlidesSettings,
    });
    try {
        const requestCache = noCache
            ? { ...cacheState, mode: "bypass", store: null }
            : cacheState;
        const runWithMode = async (resolved) => {
            if (resolved === "url")
                eventAdapter.startSlides();
            let resolvedUrlFetch = urlFetchImpl;
            const input = resolved === "url"
                ? { kind: "url", url: pageUrl, title, maxCharacters }
                : { kind: "visible-page", url: pageUrl, title, text: textContent, truncated };
            if (resolved === "url") {
                await assertDaemonUrlFetchAllowed(pageUrl);
                resolvedUrlFetch = createDaemonUrlFetchGuard(fetchImpl);
            }
            const result = await executeSummarize(toApplicationRequest({ request, input, extractOnly: false }), toApplicationRuntime({
                runId: session.id,
                env,
                fetchImpl,
                urlFetchImpl: resolvedUrlFetch,
                cache: requestCache,
                mediaCache,
            }), eventAdapter.handleEvent);
            if (result.kind !== "summary") {
                throw new Error("Internal error: expected summary result");
            }
            return result;
        };
        const result = await (async () => {
            if (mode !== "auto")
                return runWithMode(mode);
            const { primary, fallback } = resolveAutoDaemonMode({ url: pageUrl, hasText });
            try {
                return await runWithMode(primary);
            }
            catch (error) {
                if (!fallback || eventAdapter.state.emittedOutput)
                    throw error;
                eventAdapter.writeStatus("Primary failed. Trying fallback…");
                try {
                    return await runWithMode(fallback);
                }
                catch (fallbackError) {
                    const primaryMessage = error instanceof Error ? error.message : String(error);
                    const fallbackMessage = fallbackError instanceof Error ? fallbackError.message : String(fallbackError);
                    throw new Error(`Auto mode failed.\nPrimary (${primary}): ${primaryMessage}\nFallback (${fallback}): ${fallbackMessage}`);
                }
            }
        })();
        if (!session.lastMeta.model) {
            emitMeta(session, {
                model: result.usedModel,
                modelLabel: formatModelLabelForDisplay(result.usedModel),
            }, onSessionEvent);
        }
        pushToSession(session, { event: "metrics", data: buildDaemonSummaryMetrics(result) }, onSessionEvent);
        pushToSession(session, { event: "done", data: {} }, onSessionEvent);
        requestLogger?.info?.({
            event: "summarize.done",
            url: pageUrl,
            mode,
            model: result.usedModel,
            elapsedMs: Date.now() - logStartedAt,
            summaryFromCache: eventAdapter.state.summaryFromCache,
            inputSummary: eventAdapter.state.inputSummary,
            ...(includeContentLog && slidesSettings ? { slides: eventAdapter.serializeSlides() } : {}),
            ...(includeContentLog && !eventAdapter.state.summaryFromCache
                ? {
                    input: logInput,
                    extracted: eventAdapter.state.extracted,
                    summary: eventAdapter.state.summaryText,
                }
                : {}),
        });
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        pushToSession(session, { event: "error", data: { message } }, onSessionEvent);
        if (session.slidesRequested && !session.slideEvents.done) {
            emitSlidesDone(session, { ok: false, error: message }, onSessionEvent);
        }
        console.error("[summarize-daemon] summarize failed", error);
        requestLogger?.error?.({
            event: "summarize.error",
            url: request.pageUrl,
            mode: request.mode,
            elapsedMs: Date.now() - logStartedAt,
            summaryFromCache: eventAdapter.state.summaryFromCache,
            inputSummary: eventAdapter.state.inputSummary,
            ...(includeContentLog && slidesSettings ? { slides: eventAdapter.serializeSlides() } : {}),
            error: {
                message,
                stack: error instanceof Error ? error.stack : null,
            },
            ...(includeContentLog && !eventAdapter.state.summaryFromCache
                ? {
                    input: logInput,
                    extracted: eventAdapter.state.extracted,
                    summary: eventAdapter.state.summaryText || null,
                }
                : {}),
        });
    }
    finally {
        scheduleSessionCleanup({ session, sessions, refreshSessions });
    }
}
//# sourceMappingURL=server-summarize-execution.js.map