import crypto from "node:crypto";
import fs from "node:fs/promises";
import path from "node:path";
import { handleRouteError, readBody, requirePwAi, resolveProfileContext } from "./agent.shared.js";
import { resolvePathWithinRoot } from "./path-output.js";
import { toBoolean, toStringOrEmpty } from "./utils.js";
export function registerBrowserAgentDebugRoutes(app, ctx) {
    // Adapter to allow Express-typed handlers when underlying might be browser dispatcher
    const registrar = {
        get: (path, handler) => app.get(path, handler),
        post: (path, handler) => app.post(path, handler),
        delete: (path, handler) => app.delete(path, handler),
    };
    registrar.get("/console", async (req, res) => {
        // @ts-ignore -- cherry-pick upstream type mismatch
        // @ts-ignore -- cherry-pick upstream type mismatch
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
        const level = typeof req.query.level === "string" ? req.query.level : "";
        try {
            // @ts-ignore -- cherry-pick upstream type mismatch
            const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
            // @ts-ignore -- cherry-pick upstream type mismatch
            const pw = await requirePwAi(res, "console messages");
            if (!pw)
                return;
            const messages = await pw.getConsoleMessagesViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                level: level.trim() || undefined,
            });
            // @ts-ignore -- cherry-pick upstream type mismatch
            res.json({ ok: true, messages, targetId: tab.targetId });
        }
        catch (err) {
            // @ts-ignore -- cherry-pick upstream type mismatch
            handleRouteError(ctx, res, err);
        }
        // @ts-ignore -- cherry-pick upstream type mismatch
    });
    registrar.get("/errors", async (req, res) => {
        // @ts-ignore -- cherry-pick upstream type mismatch
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
        // @ts-ignore -- cherry-pick upstream type mismatch
        const clear = toBoolean(req.query.clear) ?? false;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
            // @ts-ignore -- cherry-pick upstream type mismatch
            const pw = await requirePwAi(res, "page errors");
            if (!pw)
                return;
            const result = await pw.getPageErrorsViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                // @ts-ignore -- cherry-pick upstream type mismatch
                targetId: tab.targetId,
                clear,
            });
            res.json({ ok: true, targetId: tab.targetId, ...result });
        }
        catch (err) {
            // @ts-ignore -- cherry-pick upstream type mismatch
            // @ts-ignore -- cherry-pick upstream type mismatch
            handleRouteError(ctx, res, err);
        }
    });
    registrar.get("/requests", async (req, res) => {
        // @ts-ignore -- cherry-pick upstream type mismatch
        const profileCtx = resolveProfileContext(req, res, ctx);
        // @ts-ignore -- cherry-pick upstream type mismatch
        if (!profileCtx)
            return;
        const targetId = typeof req.query.targetId === "string" ? req.query.targetId.trim() : "";
        const filter = typeof req.query.filter === "string" ? req.query.filter : "";
        const clear = toBoolean(req.query.clear) ?? false;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId || undefined);
            // @ts-ignore -- cherry-pick upstream type mismatch
            const pw = await requirePwAi(res, "network requests");
            if (!pw)
                return;
            // @ts-ignore -- cherry-pick upstream type mismatch
            const result = await pw.getNetworkRequestsViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                filter: filter.trim() || undefined,
                clear,
                // @ts-ignore -- cherry-pick upstream type mismatch
            });
            res.json({ ok: true, targetId: tab.targetId, ...result });
            // @ts-ignore -- cherry-pick upstream type mismatch
        }
        catch (err) {
            // @ts-ignore -- cherry-pick upstream type mismatch
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/trace/start", async (req, res) => {
        // @ts-ignore -- cherry-pick upstream type mismatch
        // @ts-ignore -- cherry-pick upstream type mismatch
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        // @ts-ignore -- cherry-pick upstream type mismatch
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const screenshots = toBoolean(body.screenshots) ?? undefined;
        const snapshots = toBoolean(body.snapshots) ?? undefined;
        const sources = toBoolean(body.sources) ?? undefined;
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            // @ts-ignore -- cherry-pick upstream type mismatch
            // @ts-ignore -- cherry-pick upstream type mismatch
            const pw = await requirePwAi(res, "trace start");
            if (!pw)
                return;
            await pw.traceStartViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                // @ts-ignore -- cherry-pick upstream type mismatch
                targetId: tab.targetId,
                screenshots,
                // @ts-ignore -- cherry-pick upstream type mismatch
                snapshots,
                sources,
            });
            res.json({ ok: true, targetId: tab.targetId });
        }
        catch (err) {
            // @ts-ignore -- cherry-pick upstream type mismatch
            // @ts-ignore -- cherry-pick upstream type mismatch
            handleRouteError(ctx, res, err);
        }
    });
    registrar.post("/trace/stop", async (req, res) => {
        // @ts-ignore -- cherry-pick upstream type mismatch
        const profileCtx = resolveProfileContext(req, res, ctx);
        if (!profileCtx)
            return;
        // @ts-ignore -- cherry-pick upstream type mismatch
        const body = readBody(req);
        const targetId = toStringOrEmpty(body.targetId) || undefined;
        const out = toStringOrEmpty(body.path) || "";
        try {
            const tab = await profileCtx.ensureTabAvailable(targetId);
            // @ts-ignore -- cherry-pick upstream type mismatch
            const pw = await requirePwAi(res, "trace stop");
            if (!pw)
                return;
            const id = crypto.randomUUID();
            const dir = "/tmp/clawdbot";
            await fs.mkdir(dir, { recursive: true });
            const tracePathResult = resolvePathWithinRoot({
                rootDir: dir,
                requestedPath: out,
                scopeLabel: "trace directory",
                defaultFileName: `browser-trace-${id}.zip`,
            });
            // @ts-ignore -- cherry-pick upstream type mismatch
            if (!tracePathResult.ok) {
                res.status(400).json({ error: tracePathResult.error });
                return;
            }
            const tracePath = tracePathResult.path;
            await pw.traceStopViaPlaywright({
                cdpUrl: profileCtx.profile.cdpUrl,
                targetId: tab.targetId,
                path: tracePath,
            });
            res.json({
                ok: true,
                targetId: tab.targetId,
                path: path.resolve(tracePath),
            });
        }
        catch (err) {
            // @ts-ignore -- cherry-pick upstream type mismatch
            handleRouteError(ctx, res, err);
        }
    });
}
