(function() {
    'use strict';

    var DEFAULT_BASE_URL = 'https://api.z.ai/api/coding/paas/v4';
    var DEFAULT_MODEL = 'glm-5.1';
    var STORAGE_KEY = 'zai_chat_';
    var MODE_PROMPTS = {
        chat: 'You are a helpful, knowledgeable AI assistant. Be concise and accurate.',
        coding: 'You are an expert coding assistant. Write clean, efficient, well-documented code. Always use markdown code blocks with language tags. Explain your approach briefly before and after code. Handle edge cases and errors properly.',
        brainstorm: 'You are a creative brainstorming partner. Generate diverse ideas, explore unconventional angles, build on concepts, and help evaluate trade-offs. Think freely and expansively. Present ideas in organized lists or tables when appropriate.',
        agentic: 'You are an autonomous coding agent. Break down complex tasks into clear steps. Write production-quality code with proper error handling, tests, and documentation. Think through the architecture before coding. Use tool-calling format when appropriate: [SEARCH], [CREATE_FILE], [EDIT_FILE], [RUN_COMMAND]. Always verify your work.'
    };

    var state = {
        apiKey: '',
        baseUrl: DEFAULT_BASE_URL,
        model: DEFAULT_MODEL,
        temperature: 0.7,
        maxTokens: 4096,
        streaming: true,
        webSearch: false,
        currentMode: 'chat',
        theme: 'dark',
        conversations: [],
        activeConversationId: null,
        isGenerating: false,
        abortController: null,
        streamingConvId: null,
        streamingContent: '',
        streamingResponseDiv: null,
        terminalOpen: false
    };

    function $(sel) { return document.querySelector(sel); }
    function $$(sel) { return document.querySelectorAll(sel); }

    function loadState() {
        try {
            state.apiKey = localStorage.getItem(STORAGE_KEY + 'apiKey') || '';
            state.baseUrl = localStorage.getItem(STORAGE_KEY + 'baseUrl') || DEFAULT_BASE_URL;
            state.model = localStorage.getItem(STORAGE_KEY + 'model') || DEFAULT_MODEL;
            state.temperature = parseFloat(localStorage.getItem(STORAGE_KEY + 'temperature')) || 0.7;
            state.maxTokens = parseInt(localStorage.getItem(STORAGE_KEY + 'maxTokens')) || 4096;
            state.streaming = localStorage.getItem(STORAGE_KEY + 'streaming') !== 'false';
            state.webSearch = localStorage.getItem(STORAGE_KEY + 'webSearch') === 'true';
            state.currentMode = localStorage.getItem(STORAGE_KEY + 'currentMode') || 'chat';
            state.theme = localStorage.getItem(STORAGE_KEY + 'theme') || 'dark';
            state.terminalOpen = localStorage.getItem(STORAGE_KEY + 'terminalOpen') === 'true';
            var convData = localStorage.getItem(STORAGE_KEY + 'conversations');
            state.conversations = convData ? JSON.parse(convData) : [];
            state.activeConversationId = localStorage.getItem(STORAGE_KEY + 'activeConv') || null;
        } catch(e) { console.error('Load state error:', e); }
    }

    function saveState() {
        try {
            localStorage.setItem(STORAGE_KEY + 'apiKey', state.apiKey);
            localStorage.setItem(STORAGE_KEY + 'baseUrl', state.baseUrl);
            localStorage.setItem(STORAGE_KEY + 'model', state.model);
            localStorage.setItem(STORAGE_KEY + 'temperature', state.temperature.toString());
            localStorage.setItem(STORAGE_KEY + 'maxTokens', state.maxTokens.toString());
            localStorage.setItem(STORAGE_KEY + 'streaming', state.streaming.toString());
            localStorage.setItem(STORAGE_KEY + 'webSearch', state.webSearch.toString());
            localStorage.setItem(STORAGE_KEY + 'currentMode', state.currentMode);
            localStorage.setItem(STORAGE_KEY + 'theme', state.theme);
            localStorage.setItem(STORAGE_KEY + 'terminalOpen', state.terminalOpen.toString());
            localStorage.setItem(STORAGE_KEY + 'conversations', JSON.stringify(state.conversations));
            localStorage.setItem(STORAGE_KEY + 'activeConv', state.activeConversationId || '');
        } catch(e) { console.error('Save state error:', e); }
    }

    function genId() { return Date.now().toString(36) + Math.random().toString(36).substr(2, 9); }

    function getConversation(id) {
        var targetId = id || state.activeConversationId;
        if (!targetId) return null;
        return state.conversations.find(function(c) { return c.id === targetId; });
    }

    function flushStreamingToConversation() {
        if (state.streamingConvId && state.streamingContent) {
            var conv = getConversation(state.streamingConvId);
            if (conv) {
                var lastMsg = conv.messages[conv.messages.length - 1];
                if (lastMsg && lastMsg.role === 'assistant' && lastMsg._streaming) {
                    lastMsg.content = state.streamingContent;
                    delete lastMsg._streaming;
                } else {
                    conv.messages.push({ role: 'assistant', content: state.streamingContent });
                }
                saveState();
            }
        }
        state.streamingConvId = null;
        state.streamingContent = '';
        state.streamingResponseDiv = null;
    }

    function newConversation() {
        flushStreamingToConversation();
        if (state.isGenerating) {
            stopGeneration();
        }
        var conv = {
            id: genId(),
            title: 'New Chat',
            mode: state.currentMode,
            messages: [],
            createdAt: Date.now()
        };
        state.conversations.unshift(conv);
        state.activeConversationId = conv.id;
        state.isGenerating = false;
        state.abortController = null;
        saveState();
        renderConversationList();
        renderMessages();
        updateHeader();
        updateSendButton();
        updateTerminalVisibility();
    }

    function switchConversation(id) {
        if (id === state.activeConversationId) {
            closeSidebar();
            return;
        }
        flushStreamingToConversation();
        if (state.isGenerating) {
            stopGeneration();
            state.isGenerating = false;
            state.abortController = null;
        }
        state.activeConversationId = id;
        var conv = getConversation();
        if (conv) {
            state.currentMode = conv.mode || 'chat';
            updateModeSelector();
        }
        saveState();
        renderConversationList();
        renderMessages();
        updateHeader();
        updateSendButton();
        updateTerminalVisibility();
        closeSidebar();
    }

    function deleteConversation(id) {
        if (state.streamingConvId === id) {
            flushStreamingToConversation();
            if (state.isGenerating) stopGeneration();
            state.isGenerating = false;
        }
        state.conversations = state.conversations.filter(function(c) { return c.id !== id; });
        if (state.activeConversationId === id) {
            state.activeConversationId = state.conversations.length > 0 ? state.conversations[0].id : null;
        }
        saveState();
        renderConversationList();
        renderMessages();
        updateHeader();
        updateTerminalVisibility();
    }

    function updateHeader() {
        var conv = getConversation();
        $('#conversation-title').textContent = conv ? conv.title : 'Z.AI Chat';
        $('#current-mode-label').textContent = state.currentMode.charAt(0).toUpperCase() + state.currentMode.slice(1);
    }

    function showScreen(name) {
        $$('.screen').forEach(function(s) { s.classList.remove('active'); });
        $('#' + name + '-screen').classList.add('active');
    }

    function autoResize(el) {
        el.style.height = 'auto';
        el.style.height = Math.min(el.scrollHeight, 120) + 'px';
    }

    function renderConversationList() {
        var list = $('#conversation-list');
        if (!list) return;
        list.innerHTML = '';
        state.conversations.forEach(function(conv) {
            var div = document.createElement('div');
            div.className = 'conv-item' + (conv.id === state.activeConversationId ? ' active' : '');
            var msgCount = conv.messages.length;
            div.innerHTML = '<span class="conv-title">' + escapeHtml(conv.title) +
                (msgCount > 0 ? ' <span style="color:var(--text-muted);font-size:11px">(' + msgCount + ')</span>' : '') +
                '</span>' +
                '<button class="conv-delete" data-id="' + conv.id + '">&times;</button>';
            div.addEventListener('click', function(e) {
                if (e.target.classList.contains('conv-delete')) {
                    e.stopPropagation();
                    deleteConversation(e.target.dataset.id);
                    return;
                }
                switchConversation(conv.id);
            });
            list.appendChild(div);
        });
    }

    function escapeHtml(text) {
        var d = document.createElement('div');
        d.textContent = text;
        return d.innerHTML;
    }

    function renderMarkdown(text) {
        if (typeof marked !== 'undefined') {
            marked.setOptions({
                highlight: function(code, lang) {
                    if (typeof hljs !== 'undefined' && lang && hljs.getLanguage(lang)) {
                        try { return hljs.highlight(code, { language: lang }).value; } catch(e) {}
                    }
                    return code;
                },
                breaks: true,
                gfm: true
            });
            return marked.parse(text);
        }
        return text.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\n/g, '<br>');
    }

    function addCodeHeaders(container) {
        container.querySelectorAll('pre code').forEach(function(block) {
            var pre = block.parentElement;
            var lang = (block.className.match(/language-(\w+)/) || [])[1] || 'code';
            if (!pre.previousElementSibling || !pre.previousElementSibling.classList.contains('code-header')) {
                var header = document.createElement('div');
                header.className = 'code-header';
                header.innerHTML = '<span>' + escapeHtml(lang) + '</span><button class="copy-btn">Copy</button>';
                pre.parentElement.insertBefore(header, pre);
                header.querySelector('.copy-btn').addEventListener('click', function() {
                    navigator.clipboard.writeText(block.textContent).then(function() {
                        this.textContent = 'Copied!';
                        setTimeout(function() { this.textContent = 'Copy'; }.bind(this), 2000);
                    }.bind(this));
                });
            }
        });
    }

    function renderMessages() {
        var container = $('#messages');
        if (!container) return;
        container.innerHTML = '';
        var conv = getConversation();
        if (!conv || conv.messages.length === 0) {
            container.innerHTML = '<div class="message system">Start a conversation with Z.AI</div>';
            return;
        }
        conv.messages.forEach(function(msg) {
            appendMessage(msg.role, msg.content, container, false);
        });
        container.scrollTop = container.scrollHeight;
        updateTerminalContent();
    }

    function appendMessage(role, content, container, animate) {
        container = container || $('#messages');
        var div = document.createElement('div');
        div.className = 'message ' + role;
        if (animate === false) div.style.animation = 'none';

        if (role === 'assistant') {
            div.innerHTML = renderMarkdown(content);
            addCodeHeaders(div);
        } else {
            div.textContent = content;
        }
        container.appendChild(div);
        container.scrollTop = container.scrollHeight;
        return div;
    }

    function updateStreamingMessage(div, content) {
        div.innerHTML = renderMarkdown(content);
        addCodeHeaders(div);
        $('#messages').scrollTop = $('#messages').scrollHeight;
    }

    function showThinking() {
        var container = $('#messages');
        var div = document.createElement('div');
        div.className = 'message assistant';
        div.id = 'thinking-msg';
        div.innerHTML = '<div class="thinking-indicator"><div class="thinking-dots"><span></span><span></span><span></span></div> Thinking...</div>';
        container.appendChild(div);
        container.scrollTop = container.scrollHeight;
    }

    function removeThinking() {
        var el = $('#thinking-msg');
        if (el) el.remove();
    }

    async function sendMessage() {
        var input = $('#message-input');
        var text = input.value.trim();
        if (!text || state.isGenerating) return;

        if (!state.apiKey) {
            showScreen('setup');
            return;
        }

        if (!state.activeConversationId) {
            newConversation();
        }

        var conv = getConversation();
        if (!conv) return;

        conv.mode = state.currentMode;

        if (conv.messages.length === 0) {
            conv.title = text.substring(0, 50) + (text.length > 50 ? '...' : '');
            updateHeader();
            renderConversationList();
        }

        conv.messages.push({ role: 'user', content: text });
        saveState();
        input.value = '';
        autoResize(input);
        updateSendButton();
        appendMessage('user', text);

        state.isGenerating = true;
        state.streamingConvId = conv.id;
        state.streamingContent = '';
        updateSendButton();
        showThinking();

        try {
            var systemPrompt = MODE_PROMPTS[state.currentMode] || MODE_PROMPTS.chat;
            var apiMessages = [{ role: 'system', content: systemPrompt }];
            conv.messages.forEach(function(m) {
                if (m.role === 'user' || (m.role === 'assistant' && !m._streaming)) {
                    apiMessages.push({ role: m.role, content: m.content });
                }
            });

            var requestBody = {
                model: state.model,
                messages: apiMessages,
                temperature: state.temperature,
                max_tokens: state.maxTokens,
                stream: state.streaming
            };

            if (state.webSearch) {
                requestBody.tools = [{
                    type: 'web_search',
                    web_search: { search_query: text, search_result: true }
                }];
            }

            removeThinking();
            var responseDiv = appendMessage('assistant', '');
            state.streamingResponseDiv = responseDiv;

            if (state.streaming) {
                await streamResponse(requestBody, responseDiv, conv);
            } else {
                var result = await apiRequest(requestBody);
                var content = result.choices[0].message.content;
                updateStreamingMessage(responseDiv, content);
                state.streamingContent = content;
                conv.messages.push({ role: 'assistant', content: content });
            }
        } catch(err) {
            removeThinking();
            if (err.name !== 'AbortError') {
                appendMessage('system', 'Error: ' + (err.message || 'Request failed'));
            }
            if (state.streamingContent) {
                conv.messages.push({ role: 'assistant', content: state.streamingContent, _streaming: false });
            }
        } finally {
            state.isGenerating = false;
            state.abortController = null;
            state.streamingConvId = null;
            state.streamingResponseDiv = null;
            updateSendButton();
            saveState();
            updateTerminalContent();
        }
    }

    async function apiRequest(body) {
        var url = state.baseUrl.replace(/\/+$/, '') + '/chat/completions';
        var resp = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + state.apiKey,
                'Accept-Language': 'en-US,en'
            },
            body: JSON.stringify(body)
        });
        if (!resp.ok) {
            var errData = {};
            try { errData = await resp.json(); } catch(e) {}
            throw new Error(errData.error?.message || 'API error ' + resp.status);
        }
        return await resp.json();
    }

    var _streamAutoSaveCounter = 0;

    async function streamResponse(body, responseDiv, conv) {
        state.abortController = new AbortController();
        body.stream = true;

        var url = state.baseUrl.replace(/\/+$/, '') + '/chat/completions';
        var resp = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + state.apiKey,
                'Accept-Language': 'en-US,en'
            },
            body: JSON.stringify(body),
            signal: state.abortController.signal
        });

        if (!resp.ok) {
            var errData = {};
            try { errData = await resp.json(); } catch(e) {}
            throw new Error(errData.error?.message || 'API error ' + resp.status);
        }

        var reader = resp.body.getReader();
        var decoder = new TextDecoder();
        var fullContent = '';
        var buffer = '';
        _streamAutoSaveCounter = 0;

        while (true) {
            var chunk = await reader.read();
            if (chunk.done) break;

            buffer += decoder.decode(chunk.value, { stream: true });
            var lines = buffer.split('\n');
            buffer = lines.pop() || '';

            for (var i = 0; i < lines.length; i++) {
                var line = lines[i].trim();
                if (!line || !line.startsWith('data:')) continue;
                var data = line.substring(5).trim();
                if (data === '[DONE]') break;

                try {
                    var parsed = JSON.parse(data);
                    var delta = parsed.choices && parsed.choices[0] && parsed.choices[0].delta;
                    if (delta && delta.content) {
                        fullContent += delta.content;
                        state.streamingContent = fullContent;
                        if (responseDiv && responseDiv.parentElement) {
                            updateStreamingMessage(responseDiv, fullContent);
                        }
                        _streamAutoSaveCounter++;
                        if (_streamAutoSaveCounter % 20 === 0) {
                            _saveStreamingProgress(conv, fullContent);
                        }
                    }
                } catch(e) {}
            }
        }

        conv.messages.push({ role: 'assistant', content: fullContent });
        state.streamingContent = '';
    }

    function _saveStreamingProgress(conv, content) {
        if (!conv) return;
        var last = conv.messages[conv.messages.length - 1];
        if (last && last.role === 'assistant' && last._streaming) {
            last.content = content;
        } else {
            conv.messages.push({ role: 'assistant', content: content, _streaming: true });
        }
        saveState();
    }

    function stopGeneration() {
        if (state.abortController) {
            state.abortController.abort();
        }
        flushStreamingToConversation();
    }

    function updateSendButton() {
        var input = $('#message-input');
        var sendBtn = $('#send-btn');
        var stopBtn = $('#stop-btn');

        if (state.isGenerating) {
            sendBtn.style.display = 'none';
            stopBtn.style.display = 'flex';
        } else {
            sendBtn.style.display = 'flex';
            stopBtn.style.display = 'none';
            sendBtn.disabled = !input.value.trim();
        }
    }

    function updateModeSelector() {
        $$('.mode-btn').forEach(function(btn) {
            btn.classList.toggle('active', btn.dataset.mode === state.currentMode);
        });
    }

    function openSidebar() {
        $('#sidebar').classList.add('open');
        $('#sidebar-overlay').classList.add('active');
    }

    function closeSidebar() {
        $('#sidebar').classList.remove('open');
        $('#sidebar-overlay').classList.remove('active');
    }

    function applyTheme(theme) {
        state.theme = theme;
        document.documentElement.setAttribute('data-theme', theme);
        var headerBtn = $('#theme-toggle-header');
        if (headerBtn) {
            headerBtn.innerHTML = theme === 'dark' ? '&#9788;' : '&#9790;';
            headerBtn.title = theme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode';
        }
        var settingsToggle = $('#settings-darkmode');
        if (settingsToggle) settingsToggle.checked = (theme === 'dark');
        var metaTheme = document.querySelector('meta[name="theme-color"]');
        if (metaTheme) metaTheme.content = theme === 'dark' ? '#1a1a2e' : '#ffffff';
        saveState();
    }

    function toggleTheme() {
        applyTheme(state.theme === 'dark' ? 'light' : 'dark');
    }

    // ---- Terminal Panel ----

    function parseTerminalEntries(content) {
        if (!content) return [];
        var entries = [];

        var toolRegex = /\[(CREATE_FILE|EDIT_FILE|DELETE_FILE|RUN_COMMAND|SEARCH|READ_FILE|BUILD|TEST)\]\s*\(([^)]*)\)\s*\n?([\s\S]*?)(?=\n\[|$)/gi;
        var match;
        while ((match = toolRegex.exec(content)) !== null) {
            entries.push({
                type: 'tool',
                action: match[1],
                target: match[2].trim(),
                body: match[3].trim()
            });
        }

        var codeBlockRegex = /```(\w*)\n([\s\S]*?)```/gi;
        var idx = 0;
        while ((match = codeBlockRegex.exec(content)) !== null) {
            var isTool = false;
            for (var e = 0; e < entries.length; e++) {
                if (entries[e].type === 'tool' && match.index >= content.indexOf(entries[e].body) - 20) {
                    isTool = true;
                    break;
                }
            }
            if (!isTool) {
                idx++;
                var firstLine = match[2].trim().split('\n')[0];
                var isFilePath = /^(\/|\.\/|\.\.\/|[A-Za-z]:\\|[a-zA-Z0-9_\-]+\.[a-zA-Z]{1,4}$)/.test(firstLine) && firstLine.length < 120 && firstLine.split('\n').length === 1;
                entries.push({
                    type: 'code',
                    lang: match[1] || 'text',
                    code: match[2].trim(),
                    index: idx,
                    fileName: isFilePath ? firstLine : null
                });
            }
        }

        entries.sort(function(a, b) {
            return content.indexOf(a.type === 'tool' ? '[' + a.action : '```' + (a.lang || '')) -
                   content.indexOf(b.type === 'tool' ? '[' + b.action : '```' + (b.lang || ''));
        });

        return entries;
    }

    function renderTerminalEntry(entry) {
        if (entry.type === 'tool') {
            var actionIcon = { CREATE_FILE: '+', EDIT_FILE: '~', DELETE_FILE: '-', RUN_COMMAND: '>', SEARCH: '?', READ_FILE: 'R', BUILD: 'B', TEST: 'T' };
            var actionColor = { CREATE_FILE: 'var(--success)', EDIT_FILE: 'var(--warning)', DELETE_FILE: 'var(--danger)', RUN_COMMAND: 'var(--accent)', SEARCH: 'var(--text-secondary)', READ_FILE: 'var(--text-muted)', BUILD: 'var(--accent)', TEST: 'var(--success)' };
            var icon = actionIcon[entry.action] || '>';
            var color = actionColor[entry.action] || 'var(--accent)';
            var html = '<div class="term-entry term-tool" style="border-left:3px solid ' + color + '">';
            html += '<div class="term-tool-header"><span class="term-action" style="color:' + color + '">[' + icon + '] ' + escapeHtml(entry.action) + '</span>';
            if (entry.target) html += ' <span class="term-target">' + escapeHtml(entry.target) + '</span>';
            html += '</div>';
            if (entry.body) {
                html += '<pre class="term-code">' + escapeHtml(entry.body.substring(0, 2000)) + (entry.body.length > 2000 ? '\n... (truncated)' : '') + '</pre>';
            }
            html += '</div>';
            return html;
        }
        if (entry.type === 'code') {
            var label = entry.fileName ? escapeHtml(entry.fileName) : escapeHtml(entry.lang || 'code');
            var displayCode = entry.fileName ? entry.code.split('\n').slice(1).join('\n') : entry.code;
            if (!displayCode.trim()) displayCode = entry.code;
            var html = '<div class="term-entry term-code-block">';
            html += '<div class="term-file-header"><span class="term-lang">' + label + '</span>';
            html += '<button class="term-copy-btn" data-code="' + escapeHtml(entry.code).replace(/"/g, '&quot;') + '">Copy</button></div>';
            html += '<pre class="term-code">' + escapeHtml(displayCode.substring(0, 3000)) + (displayCode.length > 3000 ? '\n... (truncated)' : '') + '</pre>';
            html += '</div>';
            return html;
        }
        return '';
    }

    function updateTerminalContent() {
        var termBody = $('#terminal-body');
        if (!termBody) return;
        termBody.innerHTML = '';

        var conv = getConversation();
        if (!conv) return;

        var lastAssistant = null;
        for (var i = conv.messages.length - 1; i >= 0; i--) {
            if (conv.messages[i].role === 'assistant') {
                lastAssistant = conv.messages[i];
                break;
            }
        }

        if (!lastAssistant && !state.streamingContent) {
            termBody.innerHTML = '<div class="term-empty">No code output yet. Use Coding or Agentic mode to generate code.</div>';
            return;
        }

        var content = state.streamingContent || (lastAssistant ? lastAssistant.content : '');
        var entries = parseTerminalEntries(content);

        if (entries.length === 0) {
            termBody.innerHTML = '<div class="term-empty">No structured code blocks or tool calls detected in response.</div>';
            return;
        }

        entries.forEach(function(entry) {
            termBody.innerHTML += renderTerminalEntry(entry);
        });

        termBody.querySelectorAll('.term-copy-btn').forEach(function(btn) {
            btn.addEventListener('click', function() {
                var code = this.getAttribute('data-code').replace(/&quot;/g, '"').replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
                navigator.clipboard.writeText(code).then(function() {
                    this.textContent = 'Copied!';
                    setTimeout(function() { this.textContent = 'Copy'; }.bind(this), 2000);
                }.bind(this));
            });
        });

        if (state.terminalOpen) {
            termBody.scrollTop = termBody.scrollHeight;
        }
    }

    function updateTerminalVisibility() {
        var panel = $('#terminal-panel');
        var toggleBtn = $('#terminal-toggle');
        if (!panel || !toggleBtn) return;

        var isDevMode = (state.currentMode === 'coding' || state.currentMode === 'agentic');
        if (isDevMode) {
            panel.style.display = 'flex';
            toggleBtn.style.display = 'flex';
        } else {
            panel.style.display = 'none';
            toggleBtn.style.display = 'none';
            state.terminalOpen = false;
        }

        if (state.terminalOpen && isDevMode) {
            panel.classList.add('open');
        } else {
            panel.classList.remove('open');
        }

        var label = toggleBtn.querySelector('.terminal-label');
        if (label) label.textContent = state.terminalOpen ? 'Hide Terminal' : 'Show Terminal';
    }

    function toggleTerminal() {
        state.terminalOpen = !state.terminalOpen;
        var panel = $('#terminal-panel');
        if (panel) panel.classList.toggle('open', state.terminalOpen);
        var label = $('#terminal-toggle .terminal-label');
        if (label) label.textContent = state.terminalOpen ? 'Hide Terminal' : 'Show Terminal';
        if (state.terminalOpen) updateTerminalContent();
        saveState();
    }

    // ---- Rest of init ----

    async function testConnection(apiKey, baseUrl) {
        var url = (baseUrl || state.baseUrl).replace(/\/+$/, '') + '/chat/completions';
        var resp = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + apiKey,
                'Accept-Language': 'en-US,en'
            },
            body: JSON.stringify({
                model: state.model,
                messages: [{ role: 'user', content: 'Hi' }],
                max_tokens: 10
            })
        });
        if (!resp.ok) {
            var errData = {};
            try { errData = await resp.json(); } catch(e) {}
            throw new Error(errData.error?.message || 'Connection failed (' + resp.status + ')');
        }
        return await resp.json();
    }

    function populateSettings() {
        $('#settings-token').value = state.apiKey;
        $('#settings-url').value = state.baseUrl;
        $('#settings-model').value = state.model;
        $('#settings-temp').value = state.temperature;
        $('#temp-value').textContent = state.temperature;
        $('#settings-tokens').value = state.maxTokens;
        $('#tokens-value').textContent = state.maxTokens;
        $('#settings-websearch').checked = state.webSearch;
        $('#settings-streaming').checked = state.streaming;
    }

    function saveSettings() {
        state.apiKey = $('#settings-token').value.trim();
        state.baseUrl = $('#settings-url').value.trim();
        state.model = $('#settings-model').value;
        state.temperature = parseFloat($('#settings-temp').value);
        state.maxTokens = parseInt($('#settings-tokens').value);
        state.webSearch = $('#settings-websearch').checked;
        state.streaming = $('#settings-streaming').checked;
        saveState();
    }

    function exportConversations() {
        var data = JSON.stringify(state.conversations, null, 2);
        var blob = new Blob([data], { type: 'application/json' });
        var url = URL.createObjectURL(blob);
        var a = document.createElement('a');
        a.href = url;
        a.download = 'zai-chat-export-' + new Date().toISOString().slice(0, 10) + '.json';
        a.click();
        URL.revokeObjectURL(url);
    }

    function init() {
        loadState();

        if (state.apiKey) {
            showScreen('chat');
            if (state.activeConversationId) {
                var conv = getConversation();
                if (conv) {
                    state.currentMode = conv.mode || 'chat';
                }
            }
            renderConversationList();
            renderMessages();
            updateHeader();
            updateModeSelector();
            updateTerminalVisibility();
            $('#api-token').value = state.apiKey;
            $('#base-url').value = state.baseUrl;
        }

        $('#connect-btn').addEventListener('click', async function() {
            var btn = this;
            var apiKey = $('#api-token').value.trim();
            var baseUrl = $('#base-url').value;
            var errorEl = $('#setup-error');

            if (!apiKey) {
                errorEl.textContent = 'Please enter your API key';
                errorEl.style.display = 'block';
                return;
            }

            btn.disabled = true;
            btn.querySelector('.btn-text').textContent = 'Connecting...';
            btn.querySelector('.btn-loader').style.display = 'inline-block';
            errorEl.style.display = 'none';

            try {
                await testConnection(apiKey, baseUrl);
                state.apiKey = apiKey;
                state.baseUrl = baseUrl;
                saveState();
                showScreen('chat');
                newConversation();
            } catch(err) {
                errorEl.textContent = err.message;
                errorEl.style.display = 'block';
            } finally {
                btn.disabled = false;
                btn.querySelector('.btn-text').textContent = 'Connect';
                btn.querySelector('.btn-loader').style.display = 'none';
            }
        });

        $('#api-token').addEventListener('keydown', function(e) {
            if (e.key === 'Enter') $('#connect-btn').click();
        });

        $('#message-input').addEventListener('input', function() {
            autoResize(this);
            updateSendButton();
        });

        $('#message-input').addEventListener('keydown', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        $('#send-btn').addEventListener('click', sendMessage);
        $('#stop-btn').addEventListener('click', stopGeneration);

        $$('.mode-btn').forEach(function(btn) {
            btn.addEventListener('click', function() {
                state.currentMode = this.dataset.mode;
                updateModeSelector();
                updateHeader();
                updateTerminalVisibility();
                saveState();
            });
        });

        $('#menu-btn').addEventListener('click', openSidebar);
        $('#sidebar-close').addEventListener('click', closeSidebar);
        $('#sidebar-overlay').addEventListener('click', closeSidebar);

        $('#new-chat-btn').addEventListener('click', function() { newConversation(); });
        $('#new-chat-sidebar').addEventListener('click', function() { newConversation(); closeSidebar(); });

        $('#settings-btn').addEventListener('click', function() {
            populateSettings();
            showScreen('settings');
        });

        $('#settings-back').addEventListener('click', function() {
            saveSettings();
            showScreen('chat');
        });

        $('#settings-temp').addEventListener('input', function() {
            $('#temp-value').textContent = this.value;
        });

        $('#settings-tokens').addEventListener('input', function() {
            $('#tokens-value').textContent = this.value;
        });

        $('#settings-token').addEventListener('change', saveSettings);
        $('#settings-url').addEventListener('change', saveSettings);
        $('#settings-model').addEventListener('change', saveSettings);
        $('#settings-websearch').addEventListener('change', saveSettings);
        $('#settings-streaming').addEventListener('change', saveSettings);

        $('#theme-toggle-header').addEventListener('click', toggleTheme);

        $('#settings-darkmode').addEventListener('change', function() {
            applyTheme(this.checked ? 'dark' : 'light');
        });

        $('#terminal-toggle').addEventListener('click', toggleTerminal);

        $('#export-btn').addEventListener('click', exportConversations);

        $('#clear-btn').addEventListener('click', function() {
            if (confirm('Clear all conversations? This cannot be undone.')) {
                state.conversations = [];
                state.activeConversationId = null;
                saveState();
                renderConversationList();
                renderMessages();
                updateHeader();
                updateTerminalContent();
            }
        });

        updateModeSelector();
        updateSendButton();
        applyTheme(state.theme);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();
