(function () {
    window.AgentFrontendModules = window.AgentFrontendModules || {};

    window.AgentFrontendModules.createBrowserPreviewModule = function createBrowserPreviewModule(deps) {
        let browserPreviewPollId = null;
        let browserPreviewObjectUrl = '';
        let browserPreviewVersion = 0;
        let browserPreviewRequestSeq = 0;
        let browserPreviewRefreshPending = false;
        let browserPreviewFailureCount = 0;
        let browserPreviewCooldownUntil = 0;
        let browserActionOverlay = null;
        let browserActionTimeout = null;

        function setBrowserPreviewVisibility(isVisible) {
            if (!deps.browserPreviewSection) return;
            deps.browserPreviewSection.dataset.visible = 'true';
            deps.browserPreviewSection.dataset.active = isVisible ? 'true' : 'false';
        }

        function setBrowserPreviewCollapsed(collapsed) {
            if (!deps.browserPreviewSection) return;
            deps.browserPreviewSection.classList.toggle('browser-preview-collapsed', collapsed);
            if (collapsed) {
                deps.browserPreviewSection.classList.remove('browser-preview-fullscreen');
            }
            if (deps.chatBrowserLayout) {
                deps.chatBrowserLayout.classList.toggle('browser-pane-collapsed', collapsed);
            }
            const agentPanel = deps.browserPreviewSection.closest('.agent-panel');
            if (agentPanel) agentPanel.classList.toggle('browser-strip-collapsed', collapsed);
            if (deps.browserPreviewFullscreenBtn) {
                deps.browserPreviewFullscreenBtn.hidden = collapsed;
                deps.browserPreviewFullscreenBtn.setAttribute('aria-hidden', collapsed ? 'true' : 'false');
                deps.browserPreviewFullscreenBtn.title = 'Full screen browser view';
            }
            if (deps.browserPreviewCollapseBtn) {
                deps.browserPreviewCollapseBtn.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
                deps.browserPreviewCollapseBtn.title = collapsed ? 'Open browser view' : 'Close browser view';
            }
            localStorage.setItem(deps.collapsedStorageKey, collapsed ? '1' : '0');
        }

        function revokeBrowserPreviewObjectUrl() {
            if (browserPreviewObjectUrl) {
                URL.revokeObjectURL(browserPreviewObjectUrl);
                browserPreviewObjectUrl = '';
            }
        }

        function setBrowserPreviewMessage(message, isActive) {
            if (deps.browserPreviewStatus) deps.browserPreviewStatus.textContent = message;
            if (deps.browserPreviewSection) deps.browserPreviewSection.dataset.active = isActive ? 'true' : 'false';
        }

        async function loadBrowserPreviewImage(version) {
            const seq = ++browserPreviewRequestSeq;
            const response = await deps.authFetch(`/api/browser/preview?v=${encodeURIComponent(version || Date.now())}`);
            if (!response.ok) throw new Error(`HTTP ${response.status}`);
            const blob = await response.blob();
            const objectUrl = URL.createObjectURL(blob);
            if (seq !== browserPreviewRequestSeq) {
                URL.revokeObjectURL(objectUrl);
                return;
            }
            const previous = browserPreviewObjectUrl;
            browserPreviewObjectUrl = objectUrl;
            if (deps.browserPreviewImage) deps.browserPreviewImage.src = objectUrl;
            if (previous) URL.revokeObjectURL(previous);
        }

        async function refreshBrowserPreview(forceImage) {
            if (!deps.browserPreviewSection) return;
            if (browserPreviewRefreshPending) return;
            if (!forceImage && browserPreviewCooldownUntil && Date.now() < browserPreviewCooldownUntil) return;
            browserPreviewRefreshPending = true;
            try {
                const state = await deps.authFetchJson('/api/browser/state');
                browserPreviewFailureCount = 0;
                browserPreviewCooldownUntil = 0;
                const active = !!state.active;
                setBrowserPreviewVisibility(active);
                const modeText = 'In-app browser';
                const statusText = state.status ? `${modeText} · ${state.status}` : `${modeText} · idle`;
                setBrowserPreviewMessage(statusText, active);

                if (deps.browserPreviewTitle) {
                    deps.browserPreviewTitle.textContent = state.title || (active ? 'Current page' : 'No page loaded');
                    deps.browserPreviewTitle.title = state.title || '';
                }

                if (deps.browserPreviewUrl) {
                    if (state.url) {
                        deps.browserPreviewUrl.href = state.url;
                        deps.browserPreviewUrl.textContent = state.url;
                        deps.browserPreviewUrl.title = state.url;
                        deps.browserPreviewUrl.style.display = '';
                    } else {
                        deps.browserPreviewUrl.removeAttribute('href');
                        deps.browserPreviewUrl.textContent = '';
                        deps.browserPreviewUrl.style.display = 'none';
                    }
                }

                if (active && state.preview_available) {
                    if (forceImage || state.preview_version !== browserPreviewVersion || !deps.browserPreviewImage?.src) {
                        await loadBrowserPreviewImage(state.preview_version);
                        browserPreviewVersion = state.preview_version;
                    }
                    if (deps.browserPreviewImage) deps.browserPreviewImage.style.display = '';
                    if (deps.browserPreviewEmpty) deps.browserPreviewEmpty.style.display = 'none';
                } else {
                    if (deps.browserPreviewImage) deps.browserPreviewImage.style.display = 'none';
                    if (deps.browserPreviewEmpty) {
                        deps.browserPreviewEmpty.textContent = active
                            ? 'Browser session is active, but no preview is available yet.'
                            : 'No browser page open yet.';
                        deps.browserPreviewEmpty.style.display = '';
                    }
                }
            } catch (_) {
                browserPreviewFailureCount = Math.min(browserPreviewFailureCount + 1, 6);
                browserPreviewCooldownUntil = Date.now() + Math.min(30000, 1000 * (2 ** browserPreviewFailureCount));
                setBrowserPreviewVisibility(false);
                setBrowserPreviewMessage('Browser preview unavailable.', false);
                if (deps.browserPreviewImage) deps.browserPreviewImage.style.display = 'none';
                if (deps.browserPreviewEmpty) {
                    deps.browserPreviewEmpty.textContent = 'Could not load the browser preview.';
                    deps.browserPreviewEmpty.style.display = '';
                }
            } finally {
                browserPreviewRefreshPending = false;
            }
        }

        function startBrowserPreviewPolling() {
            if (!deps.browserPreviewSection) return;
            if (browserPreviewPollId) clearInterval(browserPreviewPollId);
            setBrowserPreviewVisibility(false);
            refreshBrowserPreview(true);
            browserPreviewPollId = setInterval(() => {
                if (document.visibilityState === 'visible') refreshBrowserPreview(false);
            }, 1500);
        }

        function showBrowserActionOverlay(text) {
            const stage = deps.browserPreviewStage || document.getElementById('browser-preview-stage');
            if (!stage) return;
            if (!browserActionOverlay) {
                browserActionOverlay = document.createElement('div');
                browserActionOverlay.className = 'browser-action-overlay';
                stage.appendChild(browserActionOverlay);
            }
            browserActionOverlay.textContent = text;
            browserActionOverlay.style.display = '';
            browserActionOverlay.style.opacity = '1';
            if (browserActionTimeout) clearTimeout(browserActionTimeout);
            browserActionTimeout = setTimeout(() => {
                if (browserActionOverlay) {
                    browserActionOverlay.style.opacity = '0';
                    setTimeout(() => {
                        if (browserActionOverlay) browserActionOverlay.style.display = 'none';
                    }, 400);
                }
            }, 3000);
        }

        function handleBrowserUpdate(data) {
            if (!deps.browserPreviewSection) return;
            if (deps.browserPreviewSection.classList.contains('browser-preview-collapsed')) {
                setBrowserPreviewCollapsed(false);
            }
            const action = data.last_action || data.status || '';
            if (action) {
                setBrowserPreviewMessage(`In-app browser · ${action}`, true);
                showBrowserActionOverlay(action);
            }
            if (deps.browserPreviewTitle && data.title) {
                deps.browserPreviewTitle.textContent = data.title;
                deps.browserPreviewTitle.title = data.title;
            }
            if (deps.browserPreviewUrl && data.url) {
                deps.browserPreviewUrl.href = data.url;
                deps.browserPreviewUrl.textContent = data.url;
                deps.browserPreviewUrl.title = data.url;
                deps.browserPreviewUrl.style.display = '';
            }
            if (data.preview_available && data.preview_version && data.preview_version !== browserPreviewVersion) {
                loadBrowserPreviewImage(data.preview_version).then(() => {
                    browserPreviewVersion = data.preview_version;
                    if (deps.browserPreviewImage) deps.browserPreviewImage.style.display = '';
                    if (deps.browserPreviewEmpty) deps.browserPreviewEmpty.style.display = 'none';
                }).catch(() => {});
            }
            setBrowserPreviewVisibility(!!data.active);
        }

        function dispose() {
            if (browserPreviewPollId) {
                clearInterval(browserPreviewPollId);
                browserPreviewPollId = null;
            }
            if (browserActionTimeout) {
                clearTimeout(browserActionTimeout);
                browserActionTimeout = null;
            }
            revokeBrowserPreviewObjectUrl();
        }

        return {
            setBrowserPreviewCollapsed,
            refreshBrowserPreview,
            startBrowserPreviewPolling,
            handleBrowserUpdate,
            dispose,
        };
    };
})();