// ==========================================
// Switchboard Core — Editor Package (v0.31.0)
// ==========================================
// Installable .pkg that provides the code editor surface.
// Mounts into #extension-mount (surface-extension template).
//
// Uses Component.mount() for all sub-components — single source
// of truth for DOM structure. No duplicated template partials.
//
// Dependencies (loaded by base.html):
//   FileTree, CodeEditor, ChatPane, NotePanel, note-graph, PaneContainer
//   API, UI, App, sw, esc (ui-primitives)
//
// Dynamically loaded:
//   codemirror.bundle.js
// ==========================================

(function () {
    'use strict';

    const SURFACE_ID = 'editor';
    const PREFIX = 'ed';
    const NOTES_PREFIX = 'edNotes';
    const STATE_DEBOUNCE_MS = 2000;

    if (window.__SURFACE__ !== SURFACE_ID) return;

    const base = window.__BASE__ || '';

    // ── Dynamic Script Loader ────────────────────

    function _loadScript(src) {
        return new Promise((resolve, reject) => {
            if (document.querySelector('script[src*="' + src.split('?')[0] + '"]')) {
                resolve();
                return;
            }
            const s = document.createElement('script');
            s.src = base + src;
            s.type = 'module';
            s.onload = resolve;
            s.onerror = () => { resolve(); }; // Non-fatal
            document.head.appendChild(s);
        });
    }

    // ── Init ─────────────────────────────────────

    async function _init() {
        const mount = document.getElementById('extension-mount');
        if (!mount) return;

        // Hide server-rendered user menu (we mount our own in the topbar)
        const serverMenu = document.getElementById('userMenuWrap');
        if (serverMenu) serverMenu.style.display = 'none';

        // Wrap in surface container for CSS scoping
        const surface = document.createElement('div');
        surface.className = 'surface-editor';
        surface.id = 'editorSurface';
        mount.appendChild(surface);

        // Read workspace ID from query param
        const params = new URL(window.location.href).searchParams;
        const wsId = params.get('ws') || '';

        // Load workspace name
        let wsName = 'Editor';
        if (wsId && typeof API !== 'undefined') {
            try {
                const ws = await API._get('/api/v1/workspaces/' + wsId);
                wsName = ws?.name || ws?.data?.name || wsName;
            } catch (_) {}
        }

        // Build topbar
        const topbar = _buildTopbar(wsName);
        surface.appendChild(topbar);

        // Mount user menu via SDK (flyout drops down from topbar)
        if (typeof sw !== 'undefined' && sw.userMenu) {
            sw.userMenu(topbar, { flyout: 'down' });
        }

        // Build body + bootstrap
        const body = document.createElement('div');
        body.className = 'editor-body';
        body.id = 'editorBody';
        surface.appendChild(body);

        const bootstrap = _buildBootstrap();
        surface.appendChild(bootstrap);

        // Load dynamic dependencies (codemirror only — ChatPane, NotePanel, note-graph are platform scripts in base.html)
        const ver = window.__VERSION__ || '';
        const verQ = ver ? '?v=' + ver : '';
        await _loadScript('/vendor/codemirror/codemirror.bundle.js' + verQ);

        _initWsSelector(wsId);

        if (!wsId) {
            body.style.display = 'none';
            bootstrap.style.display = '';
            _loadBootstrapList();
            _initBootstrapCreate();
            return;
        }

        _mountEditor(wsId, wsName);
    }

    // ── Topbar ──────────────────────────────────

    function _buildTopbar(wsName) {
        const el = document.createElement('div');
        el.className = 'editor-topbar';
        el.id = 'editorTopbar';
        el.innerHTML =
            '<a href="' + esc(base) + '/" class="editor-topbar-back" title="Back to chat">' +
                '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"/><polyline points="12 19 5 12 12 5"/></svg>' +
                'Back' +
            '</a>' +
            '<div class="editor-topbar-sep"></div>' +
            '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="color:var(--accent);"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>' +
            '<div class="editor-ws-selector" id="editorWsSelector">' +
                '<button class="editor-ws-selector-btn" id="editorWsSelectorBtn">' +
                    '<span id="editorWorkspaceName">' + esc(wsName || 'Editor') + '</span>' +
                    '<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"/></svg>' +
                '</button>' +
                '<div class="editor-ws-dropdown" id="editorWsDropdown">' +
                    '<div id="editorWsList" class="editor-ws-list"></div>' +
                    '<div class="editor-ws-dropdown-divider"></div>' +
                    '<button class="editor-ws-dropdown-item editor-ws-new" id="editorWsNewBtn">' +
                        '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>' +
                        'New Workspace' +
                    '</button>' +
                '</div>' +
            '</div>' +
            '<div class="editor-topbar-branch" id="editorBranchBadge" style="display:none;">' +
                '<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="var(--purple)" stroke-width="2"><circle cx="12" cy="18" r="3"/><circle cx="12" cy="6" r="3"/><line x1="12" y1="9" x2="12" y2="15"/></svg>' +
                '<span id="editorBranchName" class="editor-topbar-branch-text">main</span>' +
            '</div>' +
            '<div style="flex:1;"></div>' +
            '<button class="icon-btn" id="editorRefreshBtn" title="Refresh files">' +
                '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>' +
            '</button>';
        return el;
    }

    // ── Bootstrap (no workspace) ────────────────

    function _buildBootstrap() {
        const el = document.createElement('div');
        el.className = 'editor-bootstrap';
        el.id = 'editorBootstrap';
        el.style.display = 'none';
        el.innerHTML =
            '<div class="editor-bootstrap-card">' +
                '<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" stroke-width="1.5" style="opacity:0.6;margin-bottom:12px;">' +
                    '<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>' +
                '</svg>' +
                '<h3 style="margin:0 0 16px;font-size:16px;">Open a Workspace</h3>' +
                '<div id="editorBootstrapList" style="margin-bottom:16px;">' +
                    '<div style="font-size:12px;color:var(--text-3);">Loading workspaces\u2026</div>' +
                '</div>' +
                '<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;">' +
                    '<div style="flex:1;height:1px;background:var(--border);"></div>' +
                    '<span style="font-size:11px;color:var(--text-3);text-transform:uppercase;">or create new</span>' +
                    '<div style="flex:1;height:1px;background:var(--border);"></div>' +
                '</div>' +
                '<input type="text" id="editorBootstrapName" class="editor-bootstrap-input" placeholder="Workspace name" value="workspace">' +
                '<button id="editorBootstrapBtn" class="editor-bootstrap-btn">Create Workspace</button>' +
            '</div>';
        return el;
    }

    // ── Workspace Selector ──────────────────────

    function _initWsSelector(currentWsId) {
        const btn = document.getElementById('editorWsSelectorBtn');
        const dropdown = document.getElementById('editorWsDropdown');
        if (!btn || !dropdown) return;

        btn.addEventListener('click', (e) => {
            e.stopPropagation();
            if (dropdown.classList.toggle('open')) _loadWsDropdown(currentWsId);
        });
        document.addEventListener('click', (e) => {
            if (!e.target.closest('#editorWsSelector')) dropdown.classList.remove('open');
        });
        document.getElementById('editorWsNewBtn')?.addEventListener('click', async () => {
            dropdown.classList.remove('open');
            const name = window.prompt('Workspace name:');
            if (!name) return;
            try {
                const userId = sw.user?.id;
                if (!userId) throw new Error('Not authenticated');
                const resp = await API.createWorkspace({ name: name.trim(), owner_type: 'user', owner_id: userId });
                const newId = resp.id || resp.data?.id;
                if (newId) window.location.href = base + '/s/editor?ws=' + newId;
            } catch (e) {
                if (typeof UI !== 'undefined') UI.toast('Failed: ' + e.message, 'error');
            }
        });
    }

    async function _loadWsDropdown(currentWsId) {
        const listEl = document.getElementById('editorWsList');
        if (!listEl) return;
        listEl.innerHTML = '<div style="padding:6px 12px;font-size:11px;color:var(--text-3)">Loading\u2026</div>';
        try {
            const resp = await API._get('/api/v1/workspaces');
            const workspaces = resp.data || resp || [];
            listEl.innerHTML = '';
            if (!workspaces.length) {
                listEl.innerHTML = '<div style="padding:6px 12px;font-size:11px;color:var(--text-3)">No workspaces</div>';
                return;
            }
            workspaces.forEach(ws => {
                const item = document.createElement('button');
                item.className = 'editor-ws-dropdown-item' + (ws.id === currentWsId ? ' active' : '');
                item.textContent = ws.name || ws.id?.slice(0, 8);
                item.addEventListener('click', () => { window.location.href = base + '/s/editor?ws=' + ws.id; });
                listEl.appendChild(item);
            });
        } catch (_) {
            listEl.innerHTML = '<div style="padding:6px 12px;font-size:11px;color:var(--text-3)">Failed to load</div>';
        }
    }

    // ── Bootstrap ────────────────────────────────

    async function _loadBootstrapList() {
        const listEl = document.getElementById('editorBootstrapList');
        if (!listEl) return;
        try {
            const resp = await API._get('/api/v1/workspaces');
            const workspaces = resp.data || resp || [];
            if (!workspaces.length) {
                listEl.innerHTML = '<div style="font-size:12px;color:var(--text-3);">No workspaces yet</div>';
                return;
            }
            listEl.innerHTML = '';
            workspaces.forEach(ws => {
                const item = document.createElement('button');
                item.className = 'editor-bootstrap-ws-item';
                item.innerHTML =
                    '<span class="editor-bootstrap-ws-name">' + esc(ws.name || ws.id?.slice(0, 8)) + '</span>' +
                    '<span class="editor-bootstrap-ws-date">' + esc(ws.created_at ? new Date(ws.created_at).toLocaleDateString() : '') + '</span>';
                item.addEventListener('click', () => { window.location.href = base + '/s/editor?ws=' + ws.id; });
                listEl.appendChild(item);
            });
        } catch (_) {
            listEl.innerHTML = '<div style="font-size:12px;color:var(--text-3);">Failed to load workspaces</div>';
        }
    }

    function _initBootstrapCreate() {
        const btn = document.getElementById('editorBootstrapBtn');
        const input = document.getElementById('editorBootstrapName');
        if (!btn || !input) return;
        btn.addEventListener('click', async () => {
            const name = input.value.trim() || 'workspace';
            btn.disabled = true;
            btn.textContent = 'Creating\u2026';
            try {
                const userId = sw.user?.id;
                if (!userId) throw new Error('Not authenticated');
                const resp = await API.createWorkspace({ name, owner_type: 'user', owner_id: userId });
                const newId = resp.id || resp.data?.id;
                if (!newId) throw new Error('No workspace ID returned');
                window.location.href = base + '/s/editor?ws=' + newId;
            } catch (e) {
                btn.disabled = false;
                btn.textContent = 'Create Workspace';
                if (typeof UI !== 'undefined') UI.toast('Failed: ' + e.message, 'error');
            }
        });
    }

    // ── Mount Pane Layout ───────────────────────

    function _mountEditor(wsId, wsName) {
        const body = document.getElementById('editorBody');
        if (!body) return;

        // ── Layout via SDK ──
        const layout = sw.layout(body, 'editor', { workspaceId: wsId });
        if (!layout) return;

        const filesPaneEl = layout._panes.get('files')?.el;
        const editorPaneEl = layout._panes.get('editor')?.el;
        const assistPaneInfo = layout._panes.get('assist');

        // ── FileTree via SDK ──
        let fileTree;
        if (filesPaneEl) {
            fileTree = sw.fileTree(filesPaneEl, {
                id: PREFIX, workspaceId: wsId,
                onSelect: (path) => { codeEditor?.openFile(path); _saveState(wsId, codeEditor); },
                onDelete: (path) => _deleteFile(wsId, path, fileTree, codeEditor),
                onNewFile: () => _createNewFile(wsId, fileTree),
            });
            layout._panes.get('files').component = fileTree;
        }

        // ── CodeEditor via SDK ──
        let codeEditor;
        if (editorPaneEl) {
            codeEditor = sw.codeEditor(editorPaneEl, {
                id: PREFIX, workspaceId: wsId,
                onSave: () => fileTree?.refresh(),
                onActivate: (path) => { fileTree?.setActiveFile(path); _saveState(wsId, codeEditor); },
            });
            layout._panes.get('editor').component = codeEditor;
        }

        // ── Assist pane (tabbed: chat + notes) via SDK ──
        if (assistPaneInfo?.tabs) {
            // Chat tab — standalone mode handles everything (streaming, model selector, history)
            const chatPanel = assistPaneInfo.getTabPanel('chat');
            if (chatPanel) {
                const chatPane = sw.chat(chatPanel, {
                    id: PREFIX,
                    standalone: true,
                    getContext: () => _getFileContext(codeEditor),
                });
                if (chatPane) {
                    const chatTab = assistPaneInfo.tabs.find(t => t.id === 'chat');
                    if (chatTab) chatTab.instance = chatPane;
                }
            }

            // Notes tab
            const notesPanel = assistPaneInfo.getTabPanel('notes');
            if (notesPanel) {
                const notePanel = sw.notes(notesPanel, { projectId: null });
                if (notePanel) {
                    const notesTab = assistPaneInfo.tabs.find(t => t.id === 'notes');
                    if (notesTab) {
                        notesTab.instance = notePanel;
                        const _loadNotes = () => {
                            if (!notesTab._loaded) {
                                notesTab._loaded = true;
                                notePanel.loadNotesList();
                                notePanel.loadNoteFolders();
                            }
                        };
                        notesTab.btn.addEventListener('click', _loadNotes);
                        if (notesTab._activated) _loadNotes();
                    }
                }
            }
        }

        // Git branch
        _refreshGitBranch(wsId, codeEditor);

        // Toolbar
        document.getElementById('editorRefreshBtn')?.addEventListener('click', () => {
            fileTree?.refresh();
            _refreshGitBranch(wsId, codeEditor);
        });

        // Initial load
        fileTree?.refresh();
        _restoreState(wsId, codeEditor);

        console.log('[EditorPkg] Mounted for workspace', wsId);
    }

    // ── File Operations ─────────────────────────

    async function _deleteFile(wsId, path, fileTree, codeEditor) {
        const ok = typeof showConfirm === 'function'
            ? await showConfirm('Delete ' + path + '?')
            : window.confirm('Delete ' + path + '?');
        if (!ok) return;
        try {
            await API.deleteWorkspaceFile(wsId, path);
            if (codeEditor?.getOpenFiles().includes(path)) await codeEditor.closeFile(path);
            fileTree?.refresh();
        } catch (e) {
            if (typeof UI !== 'undefined') UI.toast('Delete failed: ' + e.message, 'error');
        }
    }

    async function _createNewFile(wsId, fileTree) {
        const name = window.prompt('File name (e.g. src/main.go):');
        if (!name) return;
        try {
            await API.writeWorkspaceFile(wsId, name.trim(), '');
            fileTree?.refresh();
            if (typeof UI !== 'undefined') UI.toast('Created ' + name.trim(), 'success');
        } catch (e) {
            if (typeof UI !== 'undefined') UI.toast('Failed: ' + e.message, 'error');
        }
    }

    async function _refreshGitBranch(wsId, codeEditor) {
        try {
            const resp = await API.getWorkspaceGitBranches(wsId);
            const branch = resp.current || null;
            if (branch) {
                const badge = document.getElementById('editorBranchBadge');
                const name = document.getElementById('editorBranchName');
                if (badge) badge.style.display = '';
                if (name) name.textContent = branch;
            }
            if (codeEditor) codeEditor.setBranch(branch);
        } catch (_) {}
    }

    // ── File Context (editor-specific, passed to ChatPane via getContext) ──

    function _getFileContext(editor) {
        if (!editor) return null;
        try {
            const openFiles = editor.getOpenFiles();
            if (!openFiles.length) return null;
            const activeTab = document.querySelector('.code-editor-tab.active');
            const path = activeTab?.dataset?.path || openFiles[0];
            const inst = CodeEditor._instances?.get(PREFIX);
            if (inst?._files) {
                const file = inst._files.get(path);
                if (file?.view) return { path, content: file.view.state.doc.toString().slice(0, 4000) };
            }
        } catch (_) {}
        return null;
    }

    // ── State Persistence (localStorage) ─────────

    const STATE_KEY_PREFIX = 'sb:editor:state:';
    let _stateSaveTimer = null;

    function _stateKey(wsId) {
        return STATE_KEY_PREFIX + (sw?.user?.id || '') + ':' + wsId;
    }

    function _restoreState(wsId, codeEditor) {
        if (!wsId) return;
        try {
            const raw = localStorage.getItem(_stateKey(wsId));
            if (!raw) return;
            const state = JSON.parse(raw);
            if (state.open_tabs && Array.isArray(state.open_tabs)) {
                for (const path of state.open_tabs) codeEditor.openFile(path);
                if (state.active_tab) codeEditor.activateFile(state.active_tab);
            }
        } catch (_) {}
    }

    function _saveState(wsId, codeEditor) {
        if (_stateSaveTimer) clearTimeout(_stateSaveTimer);
        _stateSaveTimer = setTimeout(() => {
            if (!wsId) return;
            try {
                const openFiles = codeEditor.getOpenFiles();
                const activeTab = document.querySelector('.code-editor-tab.active');
                localStorage.setItem(_stateKey(wsId), JSON.stringify({
                    open_tabs: openFiles,
                    active_tab: activeTab?.dataset?.path || '',
                    updated_at: new Date().toISOString(),
                }));
            } catch (_) {}
        }, STATE_DEBOUNCE_MS);
    }

    // ── Boot ─────────────────────────────────────

    document.addEventListener('DOMContentLoaded', _init);
})();
