import { DEFAULT_UPLOAD_DIR, resolvePathsWithinRoot } from "../../browser/paths.js";
import { danger } from "../../globals.js";
import { defaultRuntime } from "../../runtime.js";
import { shortenHomePath } from "../../utils.js";
import { callBrowserRequest } from "../browser-cli-shared.js";
import { resolveBrowserActionContext } from "./shared.js";
function normalizeUploadPaths(paths) {
    const result = resolvePathsWithinRoot({
        rootDir: DEFAULT_UPLOAD_DIR,
        requestedPaths: paths,
        scopeLabel: `uploads directory (${DEFAULT_UPLOAD_DIR})`,
    });
    if (!result.ok) {
        throw new Error(result.error);
    }
    return result.paths;
}
export function registerBrowserFilesAndDownloadsCommands(browser, parentOpts) {
    browser
        .command("upload")
        .description("Arm file upload for the next file chooser")
        .argument("<paths...>", "File paths to upload (must be within OpenClaw temp uploads dir, e.g. /tmp/clawdbot-cn/uploads/file.pdf)")
        .option("--ref <ref>", "Ref id from snapshot to click after arming")
        .option("--input-ref <ref>", "Ref id for <input type=file> to set directly")
        .option("--element <selector>", "CSS selector for <input type=file>")
        .option("--target-id <id>", "CDP target id (or unique prefix)")
        .option("--timeout-ms <ms>", "How long to wait for the next file chooser (default: 120000)", (v) => Number(v))
        .action(async (paths, opts, cmd) => {
        const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
        try {
            const normalizedPaths = normalizeUploadPaths(paths);
            const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
            // @ts-ignore -- cherry-pick upstream type mismatch
            // @ts-ignore -- cherry-pick upstream type mismatch
            const result = await callBrowserRequest(parent, {
                method: "POST",
                path: "/hooks/file-chooser",
                query: profile ? { profile } : undefined,
                body: {
                    paths: normalizedPaths,
                    ref: opts.ref?.trim() || undefined,
                    inputRef: opts.inputRef?.trim() || undefined,
                    element: opts.element?.trim() || undefined,
                    targetId: opts.targetId?.trim() || undefined,
                    timeoutMs,
                },
            }, { timeoutMs: timeoutMs ?? 20000 });
            if (parent?.json) {
                defaultRuntime.log(JSON.stringify(result, null, 2));
                return;
            }
            defaultRuntime.log(`upload armed for ${paths.length} file(s)`);
        }
        catch (err) {
            defaultRuntime.error(danger(String(err)));
            defaultRuntime.exit(1);
        }
    });
    browser
        .command("waitfordownload")
        .description("Wait for the next download (and save it)")
        .argument("[path]", "Save path within openclaw temp downloads dir (default: /tmp/clawdbot-cn/downloads/...; fallback: os.tmpdir()/openclaw/downloads/...)")
        .option("--target-id <id>", "CDP target id (or unique prefix)")
        .option("--timeout-ms <ms>", "How long to wait for the next download (default: 120000)", (v) => Number(v))
        .action(async (outPath, opts, cmd) => {
        const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
        try {
            // @ts-ignore -- cherry-pick upstream type mismatch
            const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
            // @ts-ignore -- cherry-pick upstream type mismatch
            const result = await callBrowserRequest(parent, {
                method: "POST",
                path: "/wait/download",
                query: profile ? { profile } : undefined,
                body: {
                    path: outPath?.trim() || undefined,
                    targetId: opts.targetId?.trim() || undefined,
                    timeoutMs,
                },
            }, { timeoutMs: timeoutMs ?? 20000 });
            if (parent?.json) {
                defaultRuntime.log(JSON.stringify(result, null, 2));
                // @ts-ignore -- cherry-pick upstream type mismatch
                return;
            }
            // @ts-ignore -- cherry-pick upstream type mismatch
            defaultRuntime.log(`downloaded: ${shortenHomePath(result.download.path)}`);
        }
        catch (err) {
            defaultRuntime.error(danger(String(err)));
            defaultRuntime.exit(1);
        }
    });
    browser
        .command("download")
        .description("Click a ref and save the resulting download")
        .argument("<ref>", "Ref id from snapshot to click")
        .argument("<path>", "Save path within openclaw temp downloads dir (e.g. report.pdf or /tmp/clawdbot-cn/downloads/report.pdf)")
        .option("--target-id <id>", "CDP target id (or unique prefix)")
        .option("--timeout-ms <ms>", "How long to wait for the download to start (default: 120000)", (v) => Number(v))
        .action(async (ref, outPath, opts, cmd) => {
        // @ts-ignore -- cherry-pick upstream type mismatch
        const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
        try {
            const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
            // @ts-ignore -- cherry-pick upstream type mismatch
            const result = await callBrowserRequest(parent, {
                method: "POST",
                path: "/download",
                query: profile ? { profile } : undefined,
                body: {
                    ref,
                    path: outPath,
                    targetId: opts.targetId?.trim() || undefined,
                    timeoutMs,
                },
            }, { timeoutMs: timeoutMs ?? 20000 });
            // @ts-ignore -- cherry-pick upstream type mismatch
            if (parent?.json) {
                defaultRuntime.log(JSON.stringify(result, null, 2));
                return;
            }
            // @ts-ignore -- cherry-pick upstream type mismatch
            defaultRuntime.log(`downloaded: ${shortenHomePath(result.download.path)}`);
        }
        catch (err) {
            defaultRuntime.error(danger(String(err)));
            defaultRuntime.exit(1);
        }
    });
    browser
        .command("dialog")
        .description("Arm the next modal dialog (alert/confirm/prompt)")
        .option("--accept", "Accept the dialog", false)
        .option("--dismiss", "Dismiss the dialog", false)
        .option("--prompt <text>", "Prompt response text")
        .option("--target-id <id>", "CDP target id (or unique prefix)")
        .option("--timeout-ms <ms>", "How long to wait for the next dialog (default: 120000)", (v) => Number(v))
        .action(async (opts, cmd) => {
        const { parent, profile } = resolveBrowserActionContext(cmd, parentOpts);
        const accept = opts.accept ? true : opts.dismiss ? false : undefined;
        if (accept === undefined) {
            defaultRuntime.error(danger("Specify --accept or --dismiss"));
            defaultRuntime.exit(1);
            return;
        }
        try {
            const timeoutMs = Number.isFinite(opts.timeoutMs) ? opts.timeoutMs : undefined;
            const result = await callBrowserRequest(parent, {
                method: "POST",
                path: "/hooks/dialog",
                query: profile ? { profile } : undefined,
                body: {
                    accept,
                    // @ts-ignore -- cherry-pick upstream type mismatch
                    promptText: opts.prompt?.trim() || undefined,
                    targetId: opts.targetId?.trim() || undefined,
                    timeoutMs,
                },
            }, 
            // @ts-ignore -- cherry-pick upstream type mismatch
            { timeoutMs: timeoutMs ?? 20000 });
            if (parent?.json) {
                defaultRuntime.log(JSON.stringify(result, null, 2));
                return;
            }
            defaultRuntime.log("dialog armed");
        }
        catch (err) {
            defaultRuntime.error(danger(String(err)));
            defaultRuntime.exit(1);
        }
    });
}
