// Lightweight Terminal Panel singleton
(() => {
    class TerminalPanelImpl {
        constructor() {
            this.container = null; // external container passed by DrawerComponent
            this.panelEl = null;
            this.logEl = null;
            this.inputEl = null;
            this.socket = null;
            this.connectedIp = null;
            this.isOpen = false;
            this.resizeHandler = null;
            this.isMinimized = false;
            this.dockEl = null;
            this.dockBtnEl = null;
            this.lastNodeIp = null;
            this.fallbackContainer = null;

            try {
                this._onKeydown = this._onKeydown.bind(this);
                document.addEventListener('keydown', this._onKeydown);
            } catch (_) {
                // ignore if document not available
            }
        }

        open(container, nodeIp) {
            try {
                this.container = container;
                if (!this.container) return;
                if (!this.panelEl) {
                    this._buildPanel();
                }

                this.lastNodeIp = nodeIp || this.lastNodeIp;

                // Reset any leftover inline positioning so CSS centering applies
                if (this.container) {
                    this.container.style.right = '';
                    this.container.style.left = '';
                    this.container.style.top = '';
                    this.container.style.bottom = '';
                    this.container.style.width = '';
                }

                if (!this.isMinimized) {
                    if (this.panelEl) {
                        this.panelEl.classList.remove('minimized');
                        this.panelEl.classList.remove('visible');
                        requestAnimationFrame(() => {
                            this.panelEl.classList.add('visible');
                            this.inputEl && this.inputEl.focus();
                        });
                    }
                    this._hideDock();
                } else {
                    if (this.panelEl) {
                        this.panelEl.classList.remove('visible');
                        this.panelEl.classList.add('minimized');
                    }
                    this._showDock();
                }

                this.isOpen = true;

                // Connect websocket
                if (nodeIp) {
                    this._connect(nodeIp);
                } else if (this.lastNodeIp && !this.socket) {
                    this._connect(this.lastNodeIp);
                } else if (!this.socket && !this.lastNodeIp) {
                    this._updateTitle(null);
                }
            } catch (err) {
                console.error('TerminalPanel.open error:', err);
            }
        }

        close() {
            try {
                if (!this.isOpen) return;
                this.panelEl && this.panelEl.classList.remove('visible');
                this.isOpen = false;
                this.isMinimized = false;
                if (this.panelEl) this.panelEl.classList.remove('minimized');
                this._hideDock();
                if (this.socket) {
                    try { this.socket.close(); } catch (_) {}
                    this.socket = null;
                }
            } catch (err) {
                console.error('TerminalPanel.close error:', err);
            }
        }

        _buildPanel() {
            // Ensure container baseline positioning
            this.container.classList.add('terminal-panel-container');
            // Create panel DOM
            this.panelEl = document.createElement('div');
            this.panelEl.className = 'terminal-panel';
            this.panelEl.innerHTML = `
                <div class="terminal-header">
                    <div class="terminal-title">Terminal</div>
                    <div class="terminal-actions">
                        <button class="terminal-minimize-btn" title="Minimize" aria-label="Minimize">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                                <path d="M5 19h14"/>
                            </svg>
                        </button>
                        <button class="terminal-close-btn" title="Close" aria-label="Close">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
                                <path d="M18 6L6 18M6 6l12 12"/>
                            </svg>
                        </button>
                    </div>
                </div>
                <div class="terminal-body">
                    <pre class="terminal-log"></pre>
                </div>
                <div class="terminal-input-row">
                    <input type="text" class="terminal-input" placeholder="Type and press Enter to send" />
                    <button class="terminal-clear-btn" title="Clear">Clear</button>
                    <button class="terminal-send-btn">Send</button>
                </div>
            `;
            this.container.appendChild(this.panelEl);

            this.logEl = this.panelEl.querySelector('.terminal-log');
            this.inputEl = this.panelEl.querySelector('.terminal-input');
            const sendBtn = this.panelEl.querySelector('.terminal-send-btn');
            const closeBtn = this.panelEl.querySelector('.terminal-close-btn');
            const clearBtn = this.panelEl.querySelector('.terminal-clear-btn');
            const minimizeBtn = this.panelEl.querySelector('.terminal-minimize-btn');

            const sendHandler = () => {
                const value = (this.inputEl && this.inputEl.value) || '';
                if (!value) return;
                this._send(value);
                this.inputEl.value = '';
            };

            if (sendBtn) sendBtn.addEventListener('click', (e) => { e.stopPropagation(); sendHandler(); });
            if (this.inputEl) this.inputEl.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    sendHandler();
                }
            });
            if (closeBtn) closeBtn.addEventListener('click', (e) => { e.stopPropagation(); this.close(); });
            if (clearBtn) clearBtn.addEventListener('click', (e) => { e.stopPropagation(); this._clear(); });
            if (minimizeBtn) minimizeBtn.addEventListener('click', (e) => { e.stopPropagation(); this.minimize(); });
        }

        _connect(nodeIp) {
            try {
                this._updateTitle(nodeIp);

                // Close previous socket if switching node
                if (this.socket) {
                    try { this.socket.close(); } catch (_) {}
                    this.socket = null;
                }

                const protocol = (window.location && window.location.protocol === 'https:') ? 'wss' : 'ws';
                const url = `${protocol}://${nodeIp}/ws`;
                this.connectedIp = nodeIp;
                this._appendLine(`[connecting] ${url}`);

                const ws = new WebSocket(url);
                this.socket = ws;

                ws.addEventListener('open', () => {
                    this._appendLine('[open] WebSocket connection established');
                });
                ws.addEventListener('message', (evt) => {
                    let dataStr = typeof evt.data === 'string' ? evt.data : '[binary]';
                    // Decode any HTML entities so JSON isn't shown as &quot; etc.
                    dataStr = this._decodeHtmlEntities(dataStr);
                    // Try to pretty-print JSON if applicable
                    const trimmed = dataStr.trim();
                    if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
                        try {
                            const obj = JSON.parse(trimmed);
                            const pretty = JSON.stringify(obj, null, 2);
                            this._appendLine(pretty);
                            return;
                        } catch (_) {
                            // fall through if not valid JSON
                        }
                    }
                    this._appendLine(dataStr);
                });
                ws.addEventListener('error', (evt) => {
                    this._appendLine('[error] WebSocket error');
                });
                ws.addEventListener('close', () => {
                    this._appendLine('[close] WebSocket connection closed');
                });
            } catch (err) {
                console.error('TerminalPanel._connect error:', err);
                this._appendLine(`[error] ${err.message || err}`);
            }
        }

        minimize() {
            try {
                if (!this.panelEl || this.isMinimized) return;
                this.panelEl.classList.remove('visible');
                this.panelEl.classList.add('minimized');
                this.isMinimized = true;
                this.isOpen = true;
                this._showDock();
            } catch (err) {
                console.error('TerminalPanel.minimize error:', err);
            }
        }

        restore() {
            try {
                if (!this.panelEl || !this.isMinimized) return;
                this.panelEl.classList.remove('minimized');
                requestAnimationFrame(() => {
                    this.panelEl.classList.add('visible');
                    this.inputEl && this.inputEl.focus();
                });
                this.isMinimized = false;
                this.isOpen = true;
                this._hideDock();
            } catch (err) {
                console.error('TerminalPanel.restore error:', err);
            }
        }

        _ensureDock() {
            if (this.dockEl) return this.dockEl;
            const dock = document.createElement('div');
            dock.className = 'terminal-dock';
            const button = document.createElement('button');
            button.type = 'button';
            button.className = 'terminal-dock-btn';
            button.title = 'Show Terminal';
            button.setAttribute('aria-label', 'Show Terminal');
            button.innerHTML = `
                <span class="terminal-dock-icon" aria-hidden="true">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <path d="M4 17l6-6-6-6"></path>
                        <path d="M12 19h8"></path>
                    </svg>
                </span>
                <span class="terminal-dock-label">Terminal</span>
            `;
            button.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                this.restore();
            });
            dock.appendChild(button);
            document.body.appendChild(dock);
            this.dockEl = dock;
            this.dockBtnEl = button;
            return dock;
        }

        _showDock() {
            const dock = this._ensureDock();
            if (dock) dock.classList.add('visible');
        }

        _hideDock() {
            if (this.dockEl) this.dockEl.classList.remove('visible');
        }

        _resolveContainer() {
            if (this.container && document.body && document.body.contains(this.container)) {
                return this.container;
            }

            const sharedDrawer = window.__sharedDrawerInstance;
            if (sharedDrawer && sharedDrawer.terminalPanelContainer) {
                return sharedDrawer.terminalPanelContainer;
            }

            if (this.fallbackContainer && document.body && document.body.contains(this.fallbackContainer)) {
                return this.fallbackContainer;
            }

            if (typeof document !== 'undefined') {
                const fallback = document.createElement('div');
                fallback.className = 'terminal-panel-container';
                document.body.appendChild(fallback);
                this.fallbackContainer = fallback;
                return fallback;
            }

            return null;
        }

        _onKeydown(event) {
            try {
                if (!event || event.defaultPrevented) return;
                if (event.key !== 't' && event.key !== 'T') return;
                if (event.repeat) return;
                if (event.metaKey || event.ctrlKey || event.altKey) return;

                const activeEl = document.activeElement;
                if (activeEl) {
                    const tagName = activeEl.tagName;
                    const isEditable = activeEl.isContentEditable;
                    if (isEditable || tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') {
                        return;
                    }
                }

                event.preventDefault();
                this.toggleVisibility();
            } catch (_) {
                // swallow errors from key handler to avoid breaking global listeners
            }
        }

        toggleVisibility() {
            try {
                if (this.isOpen && !this.isMinimized) {
                    this.minimize();
                    return;
                }

                if (this.isOpen && this.isMinimized) {
                    this.restore();
                    return;
                }

                const targetContainer = this._resolveContainer();
                if (!targetContainer) return;
                const targetIp = this.lastNodeIp || this.connectedIp || null;
                this.open(targetContainer, targetIp);
            } catch (err) {
                console.error('TerminalPanel.toggleVisibility error:', err);
            }
        }

        _send(text) {
            try {
                if (!this.socket || this.socket.readyState !== 1) {
                    this._appendLine('[warn] Socket not open');
                    return;
                }
                this.socket.send(text);
                this._appendLine(`> ${text}`);
            } catch (err) {
                this._appendLine(`[error] ${err.message || err}`);
            }
        }

        _updateTitle(nodeIp) {
            if (!this.panelEl) return;
            const titleEl = this.panelEl.querySelector('.terminal-title');
            if (!titleEl) return;
            titleEl.textContent = nodeIp ? `Terminal — ${nodeIp}` : 'Terminal';
        }

        _clear() {
            if (this.logEl) this.logEl.textContent = '';
        }

        _appendLine(line) {
            if (!this.logEl) return;
            const timestamp = new Date().toLocaleTimeString();
            this.logEl.textContent += `[${timestamp}] ${line}\n`;
            // Auto-scroll to bottom
            const bodyEl = this.panelEl.querySelector('.terminal-body');
            if (bodyEl) bodyEl.scrollTop = bodyEl.scrollHeight;
        }

        _decodeHtmlEntities(text) {
            try {
                const div = document.createElement('div');
                div.innerHTML = text;
                return div.textContent || div.innerText || '';
            } catch (_) {
                return text;
            }
        }
    }

    // Expose singleton API
    window.TerminalPanel = window.TerminalPanel || new TerminalPanelImpl();
})();


