/**
 * Wrapper for agent-browser CLI
 *
 * Provides a TypeScript interface to agent-browser commands for browser automation.
 * Uses the CLI approach for reliability and to leverage agent-browser's daemon architecture.
 */
import { execSync, spawn } from "child_process";
import { existsSync, mkdirSync } from "fs";
import { dirname, join } from "path";
import { fileURLToPath } from "url";
// Find the agent-browser binary in node_modules
function getAgentBrowserPath() {
    // Try relative to this module first (for development)
    const currentFile = fileURLToPath(import.meta.url);
    const projectRoot = dirname(dirname(dirname(currentFile)));
    const localPath = join(projectRoot, "node_modules", ".bin", "agent-browser");
    if (existsSync(localPath)) {
        return localPath;
    }
    // Fallback to global command
    return "agent-browser";
}
/**
 * Build CLI args from options
 */
function buildArgs(options) {
    const args = [];
    if (options.headed) {
        args.push("--headed");
    }
    if (options.cdpPort) {
        args.push("--cdp", String(options.cdpPort));
    }
    if (options.session) {
        args.push("--session", options.session);
    }
    // Always use JSON output for parsing
    args.push("--json");
    return args;
}
/**
 * Execute an agent-browser command
 */
async function execAgentBrowser(command, options = {}) {
    const args = [...buildArgs(options), ...command];
    const timeout = options.timeout || 30000;
    const agentBrowserPath = getAgentBrowserPath();
    return new Promise((resolve, reject) => {
        const proc = spawn(agentBrowserPath, args, {
            stdio: ["pipe", "pipe", "pipe"],
            timeout
        });
        let stdout = "";
        let stderr = "";
        proc.stdout?.on("data", (data) => {
            stdout += data.toString();
        });
        proc.stderr?.on("data", (data) => {
            stderr += data.toString();
        });
        proc.on("close", (code) => {
            if (code === 0) {
                resolve(stdout);
            }
            else {
                reject(new Error(`agent-browser failed (code ${code}): ${stderr || stdout}`));
            }
        });
        proc.on("error", (err) => {
            reject(new Error(`agent-browser spawn error: ${err.message}`));
        });
    });
}
/**
 * Open a URL in the browser
 */
export async function openUrl(url, options = {}) {
    try {
        const output = await execAgentBrowser(["open", url], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Take a snapshot of the current page (accessibility tree with refs)
 */
export async function snapshot(options = {}) {
    const args = ["snapshot"];
    // -i for interactive elements only (reduces tokens)
    if (options.interactive !== false) {
        args.push("-i");
    }
    // -c for compact output
    if (options.compact) {
        args.push("-c");
    }
    const output = await execAgentBrowser(args, options);
    // Parse the JSON output to extract elements
    const elements = [];
    try {
        const parsed = JSON.parse(output);
        if (parsed.success && parsed.data?.refs) {
            for (const [ref, info] of Object.entries(parsed.data.refs)) {
                const refInfo = info;
                elements.push({
                    ref: `@${ref}`,
                    role: refInfo.role || "unknown",
                    name: refInfo.name,
                    text: refInfo.text
                });
            }
        }
        return { elements, raw: parsed.data?.snapshot || output };
    }
    catch {
        // Fallback to text parsing if JSON fails
        const refPattern = /@(\w+)\s+(\w+)(?:\s+"([^"]*)")?/g;
        const matches = output.matchAll(refPattern);
        for (const match of matches) {
            elements.push({
                ref: `@${match[1]}`,
                role: match[2],
                name: match[3]
            });
        }
        return { elements, raw: output };
    }
}
/**
 * Click an element by ref or selector
 */
export async function click(target, options = {}) {
    try {
        const output = await execAgentBrowser(["click", target], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Type text into the focused element
 */
export async function type(text, options = {}) {
    try {
        const output = await execAgentBrowser(["type", text], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Fill an input field (by ref or selector)
 */
export async function fill(target, value, options = {}) {
    try {
        const output = await execAgentBrowser(["fill", target, value], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Scroll the page
 */
export async function scroll(direction, amount, options = {}) {
    try {
        const args = ["scroll", direction];
        if (amount) {
            args.push(String(amount));
        }
        const output = await execAgentBrowser(args, options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Take a screenshot
 */
export async function screenshot(outputPath, options = {}) {
    try {
        // Ensure output directory exists
        const dir = dirname(outputPath);
        if (!existsSync(dir)) {
            mkdirSync(dir, { recursive: true });
        }
        const args = ["screenshot", outputPath];
        if (options.fullPage) {
            args.push("--full-page");
        }
        await execAgentBrowser(args, options);
        return { success: true, path: outputPath };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Get console messages from the browser
 */
export async function getConsoleMessages(options = {}) {
    try {
        const output = await execAgentBrowser(["console"], options);
        // Parse JSON output
        const parsed = JSON.parse(output);
        return Array.isArray(parsed) ? parsed : [];
    }
    catch {
        return [];
    }
}
/**
 * Get page errors
 */
export async function getErrors(options = {}) {
    try {
        const output = await execAgentBrowser(["errors"], options);
        const parsed = JSON.parse(output);
        return Array.isArray(parsed) ? parsed : [];
    }
    catch {
        return [];
    }
}
/**
 * Navigate back
 */
export async function back(options = {}) {
    try {
        const output = await execAgentBrowser(["back"], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Navigate forward
 */
export async function forward(options = {}) {
    try {
        const output = await execAgentBrowser(["forward"], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Reload the page
 */
export async function reload(options = {}) {
    try {
        const output = await execAgentBrowser(["reload"], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Close the browser
 */
export async function close(options = {}) {
    try {
        const output = await execAgentBrowser(["close"], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Get the current URL
 */
export async function getCurrentUrl(options = {}) {
    try {
        const output = await execAgentBrowser(["url"], options);
        return output.trim();
    }
    catch {
        return null;
    }
}
/**
 * Get page title
 */
export async function getTitle(options = {}) {
    try {
        const output = await execAgentBrowser(["title"], options);
        return output.trim();
    }
    catch {
        return null;
    }
}
/**
 * Evaluate JavaScript in the browser
 */
export async function evaluate(expression, options = {}) {
    try {
        const output = await execAgentBrowser(["evaluate", expression], options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Wait for an element to appear
 */
export async function waitFor(selector, options = {}) {
    try {
        const args = ["wait", selector];
        if (options.timeout) {
            args.push("--timeout", String(options.timeout));
        }
        const output = await execAgentBrowser(args, options);
        return { success: true, output };
    }
    catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : String(error)
        };
    }
}
/**
 * Check if agent-browser is installed and accessible
 */
export function isAgentBrowserAvailable() {
    try {
        const agentBrowserPath = getAgentBrowserPath();
        // agent-browser doesn't have --version, just check if the binary exists and responds to --help
        execSync(`"${agentBrowserPath}" --help`, { stdio: "pipe" });
        return true;
    }
    catch {
        return false;
    }
}
/**
 * Get agent-browser path for debugging
 */
export function getAgentBrowserBinaryPath() {
    return getAgentBrowserPath();
}
//# sourceMappingURL=agent-browser.js.map