"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.registerRunScript = registerRunScript;
const logger_1 = require("../../../lib/logger");
const storage_1 = require("../../../lib/storage");
const types_1 = require("./types");
const browser_lifecycle_1 = require("./browser-lifecycle");
const schemas_1 = require("./schemas");
const vision_helper_1 = require("./vision-helper");
function registerRunScript(srv) {
    srv.registerTool('run_script', {
        title: 'Run Browser Script',
        description: 'Execute a multi-step browser script (navigate, screenshot, click, fill, etc.) ' +
            'in a single call. All steps share one page — no cross-activity session issues. ' +
            'Preferred for deterministic YAML workflows.',
        inputSchema: schemas_1.runScriptSchema,
    }, async (args) => {
        let page;
        let pageId;
        // Reuse existing page via _handle, or create a new one on first navigate
        if (args._handle) {
            try {
                ({ page, pageId } = await (0, browser_lifecycle_1.resolvePage)(args));
            }
            catch {
                // If handle resolution fails, we'll create a new page on first navigate
                page = null;
                pageId = '';
            }
        }
        else {
            page = null;
            pageId = '';
        }
        const stepResults = [];
        for (let i = 0; i < args.steps.length; i++) {
            const step = args.steps[i];
            // Navigate: reuse existing page to preserve session (cookies, localStorage, SPA state).
            // Only create a new page on the first navigate.
            if (step.action === 'navigate') {
                if (!step.url) {
                    return {
                        content: [{ type: 'text', text: JSON.stringify({
                                    error: `Step ${i}: navigate requires url`,
                                    code: types_1.RESOURCE_NOT_FOUND,
                                }) }],
                        isError: true,
                    };
                }
                if (!page) {
                    const b = await (0, browser_lifecycle_1.ensureBrowser)();
                    page = await b.newPage();
                    pageId = (0, browser_lifecycle_1.allocatePageId)();
                    browser_lifecycle_1.pages.set(pageId, page);
                }
                await page.goto(step.url, {
                    waitUntil: step.wait_until || 'load',
                    timeout: 30_000,
                });
                stepResults.push({
                    step: i,
                    action: 'navigate',
                    result: { url: step.url, title: await page.title() },
                });
                continue;
            }
            // All other actions require a page
            if (!page) {
                return {
                    content: [{ type: 'text', text: JSON.stringify({
                                error: `Step ${i}: no page available. Start with a navigate step or provide a _handle.`,
                                code: types_1.SESSION_NOT_FOUND,
                            }) }],
                    isError: true,
                };
            }
            switch (step.action) {
                case 'screenshot': {
                    if (!step.path) {
                        return {
                            content: [{ type: 'text', text: JSON.stringify({
                                        error: `Step ${i}: screenshot requires path`,
                                        code: types_1.RESOURCE_NOT_FOUND,
                                    }) }],
                            isError: true,
                        };
                    }
                    const ssBackend = (0, storage_1.getStorageBackend)();
                    const ssLocalPath = await ssBackend.getLocalPath(step.path);
                    if (step.selector) {
                        const el = await page.$(step.selector);
                        if (!el) {
                            stepResults.push({ step: i, action: 'screenshot', result: { error: `Element not found: ${step.selector}`, code: types_1.RESOURCE_NOT_FOUND } });
                            continue;
                        }
                        await el.screenshot({ path: ssLocalPath });
                    }
                    else {
                        await page.screenshot({ path: ssLocalPath, fullPage: step.full_page ?? false });
                    }
                    const { size: ssSize } = await ssBackend.commitLocalPath(step.path, ssLocalPath);
                    logger_1.loggerRegistry.info(`[lt-mcp:playwright] screenshot saved: ${step.path} (${ssSize} bytes)`);
                    const ssResult = { path: step.path, size_bytes: ssSize, url: page.url() };
                    if (step.describe) {
                        try {
                            ssResult.description = await (0, vision_helper_1.analyzeScreenshot)(step.path);
                        }
                        catch (err) {
                            ssResult.description = null;
                            ssResult.describe_error = err.message;
                        }
                    }
                    stepResults.push({ step: i, action: 'screenshot', result: ssResult });
                    break;
                }
                case 'click': {
                    if (!step.selector) {
                        return {
                            content: [{ type: 'text', text: JSON.stringify({ error: `Step ${i}: click requires selector`, code: types_1.RESOURCE_NOT_FOUND }) }],
                            isError: true,
                        };
                    }
                    await page.click(step.selector, { timeout: 10_000 });
                    await page.waitForTimeout(500);
                    stepResults.push({ step: i, action: 'click', result: { clicked: step.selector, url: page.url() } });
                    break;
                }
                case 'fill': {
                    if (!step.selector || step.value === undefined) {
                        return {
                            content: [{ type: 'text', text: JSON.stringify({ error: `Step ${i}: fill requires selector and value`, code: types_1.RESOURCE_NOT_FOUND }) }],
                            isError: true,
                        };
                    }
                    await page.fill(step.selector, step.value, { timeout: 10_000 });
                    stepResults.push({ step: i, action: 'fill', result: { filled: step.selector, value: step.value } });
                    break;
                }
                case 'wait_for': {
                    if (!step.selector) {
                        return {
                            content: [{ type: 'text', text: JSON.stringify({ error: `Step ${i}: wait_for requires selector`, code: types_1.RESOURCE_NOT_FOUND }) }],
                            isError: true,
                        };
                    }
                    await page.waitForSelector(step.selector, { timeout: step.timeout ?? 10_000 });
                    stepResults.push({ step: i, action: 'wait_for', result: { found: step.selector } });
                    break;
                }
                case 'wait_for_url': {
                    if (!step.url) {
                        return {
                            content: [{ type: 'text', text: JSON.stringify({ error: `Step ${i}: wait_for_url requires url`, code: types_1.RESOURCE_NOT_FOUND }) }],
                            isError: true,
                        };
                    }
                    const urlTimeout = step.timeout ?? 10_000;
                    if (step.not) {
                        // Wait until URL does NOT contain the pattern
                        await page.waitForFunction((pattern) => !window.location.href.includes(pattern), step.url, { timeout: urlTimeout });
                    }
                    else {
                        // Wait until URL contains the pattern
                        await page.waitForURL(`**${step.url}**`, { timeout: urlTimeout });
                    }
                    stepResults.push({ step: i, action: 'wait_for_url', result: { url: page.url(), matched: !step.not } });
                    break;
                }
                case 'wait': {
                    const ms = step.timeout ?? 2000;
                    await page.waitForTimeout(ms);
                    stepResults.push({ step: i, action: 'wait', result: { waited_ms: ms } });
                    break;
                }
                case 'evaluate': {
                    if (!step.script) {
                        return {
                            content: [{ type: 'text', text: JSON.stringify({ error: `Step ${i}: evaluate requires script`, code: types_1.RESOURCE_NOT_FOUND }) }],
                            isError: true,
                        };
                    }
                    const evalResult = await page.evaluate(step.script);
                    stepResults.push({ step: i, action: 'evaluate', result: { result: evalResult } });
                    break;
                }
            }
        }
        // Collect screenshot paths for top-level wiring (compiler can't reach nested step results)
        const screenshots = stepResults
            .filter(s => s.action === 'screenshot' && s.result.path)
            .map(s => s.result.path);
        return {
            content: [{
                    type: 'text',
                    text: JSON.stringify({
                        steps_completed: stepResults.length,
                        steps: stepResults,
                        screenshots,
                        last_screenshot_path: screenshots.length > 0 ? screenshots[screenshots.length - 1] : null,
                        page_id: pageId,
                        url: page?.url?.() ?? null,
                        _handle: pageId ? (0, browser_lifecycle_1.buildHandle)(pageId) : undefined,
                    }),
                }],
        };
    });
}
