/**
 * Render a JS-heavy page in the device's existing Chromium and return its DOM.
 *
 * This is the stateless retrieval path: each call creates its own blank target,
 * navigates, reads the rendered DOM, and closes the target. Interactive
 * automation (which keeps a page alive across calls) lives in cdp-actions.ts on
 * a persistent BrowserSession. Both share the transport primitives in
 * cdp-session.ts.
 *
 *   PUT /json/new                  create a blank target, get its WS URL
 *        │
 *        ▼
 *   ws://…/devtools/page/<id>      Page.enable → Page.navigate(url)
 *        │                         await Page.loadEventFired (load-timeout)
 *        ▼
 *   Runtime.evaluate               outerHTML + body.innerText (returnByValue)
 *        │
 *        ▼
 *   PUT /json/close/<id>           always, even on the error paths above
 */
import { CdpSession, closeTarget, createTarget, openSocket, DEFAULT_COMMAND_TIMEOUT_MS, DEFAULT_LOAD_TIMEOUT_MS, } from "./cdp-session.js";
/** Render `url` in the device Chromium and return its rendered DOM text.
 *  Always returns a structured RenderResult — never throws, never returns a
 *  silent empty page. */
export async function renderPage(url, opts, deps) {
    const loadTimeoutMs = opts.loadTimeoutMs ?? DEFAULT_LOAD_TIMEOUT_MS;
    const commandTimeoutMs = opts.commandTimeoutMs ?? DEFAULT_COMMAND_TIMEOUT_MS;
    const fail = (outcome, detail) => {
        deps.log(`[browser-render] url=${url} rendered=false outcome=${outcome} detail=${JSON.stringify(detail)}`);
        return { url, rendered: false, outcome, domBytes: 0, text: "", html: "", detail };
    };
    if (!deps.WebSocketImpl) {
        return fail("websocket-unavailable", "global WebSocket is not available on this runtime (Node < 22.4)");
    }
    if (!deps.cdpPort || Number.isNaN(deps.cdpPort)) {
        return fail("cdp-unreachable", `CDP_PORT not set or invalid (got ${JSON.stringify(deps.cdpPort)})`);
    }
    const created = await createTarget(deps, commandTimeoutMs);
    if ("outcome" in created)
        return fail(created.outcome, created.detail);
    const target = created.target;
    const opened = await openSocket(deps.WebSocketImpl, target.webSocketDebuggerUrl, commandTimeoutMs);
    if ("error" in opened) {
        await closeTarget(deps, target.id);
        return fail("cdp-unreachable", `websocket connect failed: ${opened.error}`);
    }
    const session = new CdpSession(opened.ws);
    try {
        await session.command("Page.enable", {}, commandTimeoutMs);
        const loadPromise = session.waitForEvent("Page.loadEventFired", loadTimeoutMs);
        try {
            await session.command("Page.navigate", { url }, commandTimeoutMs);
        }
        catch (err) {
            await closeTarget(deps, target.id);
            return fail("navigate-failed", err instanceof Error ? err.message : String(err));
        }
        try {
            await loadPromise;
        }
        catch (err) {
            await closeTarget(deps, target.id);
            return fail("load-timeout", err instanceof Error ? err.message : String(err));
        }
        let html = "";
        let text = "";
        try {
            const htmlRes = (await session.command("Runtime.evaluate", { expression: "document.documentElement.outerHTML", returnByValue: true }, commandTimeoutMs));
            html = typeof htmlRes?.result?.value === "string" ? htmlRes.result.value : "";
            const textRes = (await session.command("Runtime.evaluate", { expression: "document.body && document.body.innerText || ''", returnByValue: true }, commandTimeoutMs));
            text = typeof textRes?.result?.value === "string" ? textRes.result.value : "";
        }
        catch (err) {
            await closeTarget(deps, target.id);
            return fail("evaluate-failed", err instanceof Error ? err.message : String(err));
        }
        const domBytes = Buffer.byteLength(html, "utf8");
        deps.log(`[browser-render] url=${url} rendered=true domBytes=${domBytes}`);
        await closeTarget(deps, target.id);
        return { url, rendered: true, outcome: "ok", domBytes, text, html };
    }
    finally {
        try {
            opened.ws.close();
        }
        catch { /* ignore */ }
    }
}
//# sourceMappingURL=cdp-render.js.map