// Side panel script - Tree View Component with Workflow Explorer
console.log('Officeless Side Panel: Loaded');

// SVG Icons
const ICONS = {
    chevron: `<svg viewBox="0 0 16 16">
        <path d="M4 6l4 4 4-4" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
    </svg>`,
    folder: `<svg viewBox="0 0 16 16">
        <path d="M14 4h-5l-1-1H3v10h11V4z"/>
    </svg>`,
    folderOpen: `<svg viewBox="0 0 16 16">
        <path d="M14 5h-5l-1-1H3v8h11V5z"/>
    </svg>`,
    workflow: `<svg viewBox="0 0 16 16">
        <path d="M3 3h10v2H3zM3 7h7v2H3zM3 11h5v2H3z" fill="currentColor"/>
    </svg>`,
    moreVertical: `<svg viewBox="0 0 16 16" fill="currentColor">
        <circle cx="8" cy="3" r="1.5"/>
        <circle cx="8" cy="8" r="1.5"/>
        <circle cx="8" cy="13" r="1.5"/>
    </svg>`,
    external: `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
        <path d="M10 3h3v3M13 3l-7 7M7 4v5H2"/>
    </svg>`,
    copy: `<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5">
        <rect x="3" y="3" width="10" height="12" rx="1"/>
        <path d="M6 3V2a1 1 0 011-1h6a1 1 0 011 1v9a1 1 0 01-1 1h-1"/>
    </svg>`
};

let currentProjectId = null;

const NAMESPACE_KEY = '__OFFICELESS_WEB_EXTENDER__';
const STORAGE_AREA = chrome.storage.local;

class TreeView {
    constructor(containerId, data, options = {}) {
        this.container = document.getElementById(containerId);
        this.data = data;
        this.selectedId = null;
        this.onDataChange = options.onDataChange;
        this.searchQuery = '';
        this.init();
    }

    init() {
        this.render();
    }

    setSearchQuery(query) {
        this.searchQuery = (query || '').toLowerCase().trim();
        this.render();
    }

    // Check if a node matches the search query (directly or through children)
    nodeMatchesSearch(node) {
        if (!this.searchQuery) return true;
        
        const labelMatch = (node.label || '').toLowerCase().includes(this.searchQuery);
        
        if (labelMatch) return true;
        
        // Check children
        if (node.children && node.children.length > 0) {
            return node.children.some(child => this.nodeMatchesSearch(child));
        }
        
        return false;
    }

    // Filter tree data to show only matching nodes and their ancestors
    filterTreeData(data) {
        if (!this.searchQuery) return data;
        
        const filterNode = (node) => {
            // Check if this node matches directly
            const labelMatch = (node.label || '').toLowerCase().includes(this.searchQuery);
            
            // Filter children
            let filteredChildren = [];
            if (node.children && node.children.length > 0) {
                filteredChildren = node.children
                    .map(filterNode)
                    .filter(n => n !== null);
            }
            
            // Include this node if:
            // 1. It matches directly (label), OR
            // 2. It has matching children
            if (labelMatch || filteredChildren.length > 0) {
                const copy = { ...node };
                if (filteredChildren.length > 0) {
                    copy.children = filteredChildren;
                    // Auto-expand when there are filtered results
                    if (node.type === 'folder' || node.type === 'entity' || node.type === 'layer') {
                        copy.expanded = true;
                    }
                }
                return copy;
            }
            
            return null;
        };
        
        return data.map(filterNode).filter(n => n !== null);
    }

    // Highlight matching text in label
    highlightMatch(text) {
        if (!this.searchQuery) return text;
        
        const lowerText = (text || '').toLowerCase();
        const query = this.searchQuery;
        const index = lowerText.indexOf(query);
        
        if (index === -1) return text;
        
        const before = text.slice(0, index);
        const match = text.slice(index, index + query.length);
        const after = text.slice(index + query.length);
        
        return `${before}<span class="match">${match}</span>${after}`;
    }

    render() {
        this.container.innerHTML = '';
        if (!this.data || this.data.length === 0) {
            this.container.innerHTML = `
                <div style="padding: 20px; text-align: center; color: #858585;">
                    <p>No workflows found.</p>
                    <p style="font-size: 11px; margin-top: 8px;">Navigate to a Mekari Officeless Studio project to load workflows.</p>
                </div>
            `;
            return;
        }
        
        const filteredData = this.filterTreeData(this.data);
        
        if (filteredData.length === 0) {
            this.container.innerHTML = `
                <div class="no-results">
                    <p>No matching workflows found.</p>
                </div>
            `;
            return;
        }
        
        filteredData.forEach(node => {
            this.container.appendChild(this.createNodeElement(node, 0));
        });
    }

    createNodeElement(node, depth) {
        const nodeEl = document.createElement('div');
        nodeEl.className = 'tree-node';
        nodeEl.dataset.id = node.id;

        // Create item row
        const itemEl = document.createElement('div');
        itemEl.className = 'tree-item';
        if (this.selectedId === node.id) {
            itemEl.classList.add('selected');
        }

        // Indentation
        const indentEl = document.createElement('div');
        indentEl.className = 'tree-indent';
        indentEl.style.width = `${depth * 20}px`;
        itemEl.appendChild(indentEl);

        // Toggle icon (chevron)
        const toggleEl = document.createElement('div');
        toggleEl.className = 'tree-toggle';
        toggleEl.innerHTML = ICONS.chevron;
        
        if (node.type === 'folder' || node.type === 'entity' || node.type === 'layer') {
            if (node.expanded) {
                toggleEl.classList.add('expanded');
            } else {
                toggleEl.classList.add('collapsed');
            }
        } else {
            toggleEl.classList.add('leaf');
        }
        itemEl.appendChild(toggleEl);

        // Icon
        const iconEl = document.createElement('div');
        iconEl.className = 'tree-icon';
        
        if (node.type === 'workflow') {
            iconEl.innerHTML = ICONS.workflow;
            iconEl.style.color = '#75beff';
        } else {
            iconEl.classList.add('folder');
            iconEl.innerHTML = node.expanded ? ICONS.folderOpen : ICONS.folder;
        }
        itemEl.appendChild(iconEl);

        // Label
        const labelEl = document.createElement('span');
        labelEl.className = 'tree-label';
        labelEl.innerHTML = this.highlightMatch(node.label);
        itemEl.appendChild(labelEl);

        const actionsEl = this.createNodeActions(node);
        if (actionsEl) {
            itemEl.appendChild(actionsEl);
        }

        // Click handler
        itemEl.addEventListener('click', () => {
            this.handleNodeClick(node);
        });

        // Middle-click handler for "Open in new tab"
        itemEl.addEventListener('auxclick', (event) => {
            if (event.button === 1 && node.type === 'workflow' && node.workflowId) {
                event.preventDefault();
                this.openWorkflowInNewTab(node);
            }
        });

        nodeEl.appendChild(itemEl);

        // Children container
        if ((node.type === 'folder' || node.type === 'entity' || node.type === 'layer') && node.children) {
            const childrenEl = document.createElement('div');
            childrenEl.className = `tree-children ${node.expanded ? 'expanded' : 'collapsed'}`;
            
            node.children.forEach(child => {
                childrenEl.appendChild(this.createNodeElement(child, depth + 1));
            });
            
            nodeEl.appendChild(childrenEl);
        }

        return nodeEl;
    }

    toggleNode(node) {
        node.expanded = !node.expanded;
        this.render();
        this.scrollNodeIntoView(node.id);
    }

    scrollNodeIntoView(nodeId) {
        const nodeEl = this.container.querySelector(`[data-id="${nodeId}"]`);
        if (nodeEl) {
            const treeContainer = document.querySelector('.tree-container');
            if (treeContainer) {
                const nodeRect = nodeEl.getBoundingClientRect();
                const containerRect = treeContainer.getBoundingClientRect();
                
                // Check if node is out of view
                if (nodeRect.top < containerRect.top || nodeRect.bottom > containerRect.bottom) {
                    nodeEl.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                }
            }
        }
    }

    createNodeActions(node) {
        const actionsEl = document.createElement('div');
        actionsEl.className = 'tree-actions';

        if (node.type === 'workflow') {
            const moreBtn = document.createElement('button');
            moreBtn.type = 'button';
            moreBtn.className = 'tree-action-btn';
            moreBtn.title = 'More actions';
            moreBtn.innerHTML = ICONS.moreVertical;
            moreBtn.addEventListener('click', (event) => {
                event.stopPropagation();
                this.showContextMenu(event, node);
            });
            actionsEl.appendChild(moreBtn);
            return actionsEl;
        }

        return null;
    }

    showContextMenu(event, node) {
        // Remove any existing context menu
        this.hideContextMenu();

        const menu = document.createElement('div');
        menu.className = 'context-menu';
        menu.id = 'workflow-context-menu';

        // Add "Duplicate workflow" option
        if (node.workflowId) {
            this.addDuplicateWorkflowOption(menu, node);
            this.addCopyFunctionNameOption(menu, node);
            this.addOpenInNewTabOption(menu, node);
        }

        // Position the menu - expand to the left
        const rect = event.target.getBoundingClientRect();
        const menuWidth = 160; // min-width from CSS
        const menuLeft = rect.right - menuWidth;
        const menuTop = rect.bottom + 4;
        
        // Ensure menu doesn't go off the left edge of the screen
        menu.style.left = `${Math.max(0, menuLeft)}px`;
        menu.style.top = `${menuTop}px`;

        document.body.appendChild(menu);

        // Close menu when clicking outside
        const closeHandler = (e) => {
            if (!menu.contains(e.target)) {
                this.hideContextMenu();
                document.removeEventListener('click', closeHandler);
            }
        };
        setTimeout(() => document.addEventListener('click', closeHandler), 0);
    }

    async addCopyFunctionNameOption(menu, node) {
        try {
            const result = await STORAGE_AREA.get(['workflowList']);
            const workflows = result.workflowList?.workflows || [];
            const workflowData = workflows.find(wf => String(wf.id) === String(node.workflowId));

            if (workflowData?.triggerType === 'function' && workflowData.triggerName) {
                const funcName = workflowData.triggerName;
                
                const copyFuncItem = document.createElement('div');
                copyFuncItem.className = 'context-menu-item';
                copyFuncItem.innerHTML = `<span class="context-menu-icon">${ICONS.copy}</span><span>Copy function name</span>`;
                copyFuncItem.addEventListener('click', async (e) => {
                    e.stopPropagation();
                    await navigator.clipboard.writeText(funcName);
                    this.showNotification(`Function name "${funcName}" copied!`, 'success');
                    this.hideContextMenu();
                });

                menu.appendChild(copyFuncItem);
            }
        } catch (err) {
            console.error('Failed to check trigger type:', err);
        }
    }

    async addDuplicateWorkflowOption(menu, node) {
        const duplicateItem = document.createElement('div');
        duplicateItem.className = 'context-menu-item';
        duplicateItem.innerHTML = `<span class="context-menu-icon"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="10" height="12" rx="1"/><path d="M6 3V2a1 1 0 011-1h6a1 1 0 011 1v9a1 1 0 01-1 1h-1"/></svg></span><span>Duplicate workflow</span>`;
        duplicateItem.addEventListener('click', async (e) => {
            e.stopPropagation();
            this.hideContextMenu();
            this.showNotification('Duplicating workflow...', 'info');
            
            try {
                const response = await chrome.runtime.sendMessage({
                    type: 'duplicate_workflow',
                    data: { workflowId: node.workflowId }
                });
                
                if (response && response.success) {
                    const { newWorkflowId, projectId } = response;
                    if (newWorkflowId && projectId) {
                        this.showNotification('Workflow duplicated! Navigating...', 'success');
                        const path = `/my-projects/${projectId}/workflows/${newWorkflowId}`;
                        const tabId = await getActiveTabId();
                        await navigateWorkflowWithVueRouter(tabId, path);
                    } else {
                        this.showNotification('Workflow duplicated successfully!', 'success');
                    }
                } else {
                    this.showNotification(response?.error || 'Failed to duplicate workflow', 'error');
                }
            } catch (err) {
                console.error('Failed to duplicate workflow:', err);
                this.showNotification('Failed to duplicate workflow', 'error');
            }
        });

        menu.appendChild(duplicateItem);
    }

    addOpenInNewTabOption(menu, node) {
        const openTabItem = document.createElement('div');
        openTabItem.className = 'context-menu-item';
        openTabItem.innerHTML = `<span class="context-menu-icon">${ICONS.external}</span><span>Open in new tab</span>`;
        openTabItem.addEventListener('click', (e) => {
            e.stopPropagation();
            this.openWorkflowInNewTab(node);
            this.hideContextMenu();
        });
        menu.appendChild(openTabItem);
    }

    async openWorkflowInNewTab(node) {
        if (!node.workflowId || !currentProjectId) {
            console.error('[OWE] Cannot open in new tab: missing workflowId or projectId');
            return;
        }
        const url = `https://studio.mekari.com/my-projects/${currentProjectId}/workflows/${node.workflowId}`;
        
        const [currentTab] = await chrome.tabs.query({ active: true, currentWindow: true });
        if (currentTab) {
            chrome.tabs.create({ url, active: true, index: currentTab.index + 1 });
        } else {
            chrome.tabs.create({ url, active: true });
        }
    }

    hideContextMenu() {
        const existingMenu = document.getElementById('workflow-context-menu');
        if (existingMenu) {
            existingMenu.remove();
        }
    }


    showNotification(message, type = 'info') {
        // Remove any existing notification
        const existingNotif = document.getElementById('workflow-notification');
        if (existingNotif) {
            existingNotif.remove();
        }

        const notification = document.createElement('div');
        notification.id = 'workflow-notification';
        notification.className = `workflow-notification workflow-notification-${type}`;
        notification.textContent = message;

        document.body.appendChild(notification);

        // Auto-remove after 3 seconds
        setTimeout(() => {
            if (notification.parentNode) {
                notification.remove();
            }
        }, 3000);
    }

    async handleNodeClick(node) {
        this.selectedId = node.id;
        
        if (node.type === 'folder' || node.type === 'entity' || node.type === 'layer') {
            this.toggleNode(node);
            return;
        }

        this.render();
        
        if (node.type === 'workflow' && node.workflowId && currentProjectId) {
            const path = `/my-projects/${currentProjectId}/workflows/${node.workflowId}`;
            const url = `https://studio.mekari.com${path}`;
            console.log('Navigating to workflow path:', path);
            const tabId = await getActiveTabId();
            const navigatedWithRouter = await navigateWorkflowWithVueRouter(tabId, path);

            // Fallback to direct URL navigation if Vue Router doesn't work
            if (!navigatedWithRouter) {
                console.log('Vue router navigation failed. Using direct URL navigation.');
                chrome.tabs.update(tabId, { url: url });
            }
        }
    }
}

// ============================================
// TAB MANAGEMENT
// ============================================

/**
 * Initialize tab switching functionality
 */
function initTabs() {
    const tabButtons = document.querySelectorAll('.tab-button');
    
    tabButtons.forEach(button => {
        button.addEventListener('click', () => {
            const tabName = button.dataset.tab;
            switchTab(tabName);
        });
    });
}

/**
 * Switch to the specified tab
 * @param {string} tabName - 'explorer' or 'code-search'
 */
function switchTab(tabName) {
    const tabButtons = document.querySelectorAll('.tab-button');
    const tabPanels = document.querySelectorAll('.tab-panel');
    
    tabButtons.forEach(button => {
        if (button.dataset.tab === tabName) {
            button.classList.add('active');
        } else {
            button.classList.remove('active');
        }
    });
    
    tabPanels.forEach(panel => {
        if (panel.id === `${tabName}-panel`) {
            panel.classList.add('active');
        } else {
            panel.classList.remove('active');
        }
    });
}

async function getActiveTabId() {
  const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
  return tab?.id;
}

async function navigateWorkflowWithVueRouter(tabId, workflowPath) {
    if (!tabId || !workflowPath || !chrome.scripting?.executeScript) {
        return false;
    }

    const url = `https://studio.mekari.com${workflowPath}`;

    try {
        const results = await chrome.scripting.executeScript({
            target: { tabId },
            world: 'MAIN',
            func: async (path, namespaceKey, fallbackUrl) => {
                const namespace = window[namespaceKey];
                const router = namespace?.vueRouter;

                if (!router || typeof router.push !== 'function') {
                    return { ok: false, reason: 'router_unavailable' };
                }

                const currentPath = router.currentRoute.value?.fullPath;
                
                // Extract project ID from path like /my-projects/:projectId/workflows/:workflowId
                const projectIdMatch = path.match(/\/my-projects\/([^\/]+)/);
                const projectId = projectIdMatch ? projectIdMatch[1] : null;
                
                console.log('[OWE] Vue Router two-step navigation:', {
                    targetPath: path,
                    projectId,
                    currentPath
                });

                try {
                    // Step 1: Navigate to project list page first
                    if (projectId) {
                        const projectPath = `/my-projects/${projectId}`;
                        console.log('[OWE] Step 1: Navigating to project list:', projectPath);
                        
                        // Set flag to prevent workflow list fetch during navigation
                        window.__OWE_NAVIGATING__ = true;
                        console.log('[OWE] Set __OWE_NAVIGATING__ = true, current URL:', window.location.href);
                        
                        const projectResolved = router.resolve(projectPath);
                        if (projectResolved.href) {
                            await router.replace(projectResolved.href);
                            // Wait for navigation to complete
                            await new Promise(r => setTimeout(r, 200));
                        }
                    }
                    
                    // Step 2: Navigate to target workflow
                    console.log('[OWE] Step 2: Navigating to workflow:', path);
                    const workflowResolved = router.resolve({ path });
                    console.log('[OWE] Vue Router resolved workflow:', workflowResolved);
                    
                    if (!workflowResolved.href) {
                        console.warn('[OWE] Vue Router resolve failed - no href');
                        return { ok: false, reason: 'resolve_failed' };
                    }
                    
                    await router.replace(workflowResolved.href);
                    console.log('[OWE] router.replace succeeded');
                    
                    // Wait and verify route changed
                    await new Promise(r => setTimeout(r, 200));
                    const newPath = router.currentRoute.value?.fullPath;
                    const newUrl = window.location.href;
                    
                    console.log('[OWE] After navigation:', {
                        newPath,
                        newUrl,
                        pathMatches: newUrl.includes(path)
                    });
                    
                    // If Vue Router didn't update the URL properly, use hard navigation
                    if (!newUrl.includes(path)) {
                        console.log('[OWE] Vue Router did not update URL, using hard navigation');
                        window.__OWE_NAVIGATING__ = false;
                        window.location.href = fallbackUrl;
                        return { ok: false, reason: 'hard_navigation' };
                    }
                    
                    return { ok: true, newPath };
                } catch (err) {
                    console.error('[OWE] Router navigation error:', err);
                    return { ok: false, error: err.message };
                } finally {
                    // Clear navigation flag
                    window.__OWE_NAVIGATING__ = false;
                }
            },
            args: [workflowPath, NAMESPACE_KEY, url]
        });

        const [firstResult] = results || [];
        return Boolean(firstResult?.result?.ok);
    } catch (error) {
        console.error('Side Panel: Failed to navigate using chrome.scripting', error);
        return false;
    }
}

// Convert categorized workflow data to tree format
function convertToTreeData(categorized, projectId) {
    if (!categorized) return [];
    
    const entities = Object.keys(categorized).sort();
    const librariesByEntity = {};
    const regularByEntity = {};

    entities.forEach(entity => {
        const layers = Object.keys(categorized[entity]).sort();
        
        layers.forEach(layer => {
            const workflows = categorized[entity][layer] || [];
            const libWorkflows = workflows.filter(wf => (wf.name || '').startsWith('LIB'));
            const regularWorkflows = workflows.filter(wf => !(wf.name || '').startsWith('LIB'));

            if (libWorkflows.length) {
                if (!librariesByEntity[entity]) {
                    librariesByEntity[entity] = {};
                }
                librariesByEntity[entity][layer] = libWorkflows;
            }

            if (regularWorkflows.length) {
                if (!regularByEntity[entity]) {
                    regularByEntity[entity] = {};
                }
                regularByEntity[entity][layer] = regularWorkflows;
            }
        });
    });

    const buildEntityNodes = (grouped) => {
        return Object.keys(grouped).sort().map(entity => {
            const layers = Object.keys(grouped[entity]).sort();
            return {
                id: `entity-${entity}`,
                label: entity,
                type: 'entity',
                expanded: false,
                children: layers.map(layer => {
                    const workflows = grouped[entity][layer];
                    return {
                        id: `layer-${entity}-${layer}`,
                        label: layer,
                        type: 'layer',
                        expanded: false,
                        children: workflows.map(wf => ({
                            id: `workflow-${wf.id}`,
                            label: wf.name,
                            type: 'workflow',
                            workflowId: wf.id
                        })).sort((a, b) => a.label.localeCompare(b.label))
                    };
                })
            };
        });
    };

    const rootChildren = [];
    const libraryEntities = buildEntityNodes(librariesByEntity);
    if (libraryEntities.length) {
        rootChildren.push({
            id: 'folder-libraries',
            label: 'Libraries',
            type: 'folder',
            expanded: false,
            children: libraryEntities
        });
    }

    rootChildren.push(...buildEntityNodes(regularByEntity));
    
    return [{
        id: 'root',
        label: projectId ? `Project: ${projectId}` : 'WORKFLOWS',
        type: 'folder',
        expanded: true,
        children: rootChildren
    }];
}


function getExpandedIds(treeData) {
    const expandedIds = new Set();
    const visit = (nodes) => {
        if (!Array.isArray(nodes)) return;
        nodes.forEach((node) => {
            if (node.expanded) expandedIds.add(node.id);
            visit(node.children);
        });
    };
    visit(treeData);
    return expandedIds;
}

function applyExpandedState(treeData, expandedIds) {
    const visit = (nodes) => {
        if (!Array.isArray(nodes)) return;
        nodes.forEach((node) => {
            if (node.type === 'folder' || node.type === 'entity' || node.type === 'layer') {
                node.expanded = expandedIds.has(node.id);
            }
            visit(node.children);
        });
    };
    visit(treeData);
}

function reconcileTreeData(currentTreeData, incomingCategorized, projectId) {
    const expandedIds = getExpandedIds(currentTreeData);
    const newTree = convertToTreeData(incomingCategorized, projectId);
    applyExpandedState(newTree, expandedIds);
    return { tree: newTree };
}

// ===================== ACTIVITY LOG VIEWER =====================

/**
 * Format a timestamp as relative time string
 */
function formatRelativeTime(ts) {
    const diff = Date.now() - ts;
    const seconds = Math.floor(diff / 1000);
    if (seconds < 60) return 'just now';
    const minutes = Math.floor(seconds / 60);
    if (minutes < 60) return `${minutes}m ago`;
    const hours = Math.floor(minutes / 60);
    if (hours < 24) return `${hours}h ago`;
    const days = Math.floor(hours / 24);
    return `${days}d ago`;
}

/**
 * Escape HTML special characters
 */
function escapeHtml(text) {
    if (!text) return '';
    const div = document.createElement('div');
    div.textContent = text;
    return div.innerHTML;
}

// Initialize and load data
document.addEventListener('DOMContentLoaded', async () => {
    // Initialize tabs first
    initTabs();
    
    const treeView = new TreeView('tree-root', [], {});
    
    // Search functionality
    const searchInput = document.getElementById('workflow-search');
    const searchClear = document.getElementById('search-clear');
    
    let searchDebounceTimer = null;
    
    const updateClearButton = () => {
        if (searchInput.value.trim()) {
            searchClear.classList.add('visible');
        } else {
            searchClear.classList.remove('visible');
        }
    };
    
    const performSearch = (query) => {
        treeView.setSearchQuery(query);
        updateClearButton();
    };
    
    searchInput.addEventListener('input', (e) => {
        const query = e.target.value;
        updateClearButton();
        
        // Debounce search
        if (searchDebounceTimer) {
            clearTimeout(searchDebounceTimer);
        }
        searchDebounceTimer = setTimeout(() => {
            performSearch(query);
        }, 150);
    });
    
    searchClear.addEventListener('click', () => {
        searchInput.value = '';
        searchInput.focus();
        performSearch('');
    });
    
    // Keyboard shortcut: Escape to clear search
    searchInput.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
            searchInput.value = '';
            performSearch('');
        }
    });
    
    // ============================================
    // CODE SEARCH FUNCTIONALITY
    // ============================================
    
    const codeSearchInput = document.getElementById('code-search');
    const codeSearchClear = document.getElementById('code-search-clear');
    const codeSearchResults = document.getElementById('code-search-results');
    
    let codeSearchDebounceTimer = null;
    let currentCodeQuery = '';
    
    /**
     * Debounced code search
     */
    async function performCodeSearch(query) {
        currentCodeQuery = query.trim();
        
        // Update clear button visibility
        if (currentCodeQuery) {
            codeSearchClear.classList.add('visible');
        } else {
            codeSearchClear.classList.remove('visible');
            codeSearchResults.innerHTML = '';
            return;
        }
        
        // Minimum query length
        if (currentCodeQuery.length < 2) {
            codeSearchResults.innerHTML = '<div class="code-search-empty">Type at least 2 characters to search</div>';
            return;
        }
        
        // Show loading state
        codeSearchResults.innerHTML = '<div class="code-search-loading">Searching...</div>';
        
        try {
            const response = await chrome.runtime.sendMessage({
                type: 'search_code',
                query: currentCodeQuery,
                options: {
                    projectId: currentProjectId,
                    limit: 50
                }
            });
            
            if (response && response.success) {
                renderCodeSearchResults(response.results);
            } else {
                codeSearchResults.innerHTML = '<div class="code-search-error">Search failed: ' + (response?.error || 'Unknown error') + '</div>';
            }
        } catch (err) {
            console.error('Side Panel: Code search error:', err);
            codeSearchResults.innerHTML = '<div class="code-search-error">Search error: ' + err.message + '</div>';
        }
    }
    
    /**
     * Render code search results
     */
    function renderCodeSearchResults(results) {
        if (!results || results.length === 0) {
            codeSearchResults.innerHTML = '<div class="code-search-empty">No results found</div>';
            return;
        }
        
        codeSearchResults.innerHTML = results.map(result => `
            <div class="code-search-result" data-workflow-id="${result.workflow_id}">
                <div class="code-result-header">
                    <div class="code-result-workflow">${escapeHtml(result.workflow_name)}</div>
                    <span class="code-result-type ${result.trigger_type || 'unknown'}">${result.trigger_type || 'unknown'}</span>
                </div>
                <div class="code-result-action">${escapeHtml(result.action_name)}</div>
                <div class="code-result-snippet">${result.snippet || ''}</div>
            </div>
        `).join('');
        
        // Add click handlers
        codeSearchResults.querySelectorAll('.code-search-result').forEach((el, index) => {
            el.addEventListener('click', () => {
                const workflowId = el.dataset.workflowId;
                const result = results[index];
                if (workflowId && currentProjectId && result) {
                    navigateToWorkflow(workflowId, result.action_name, currentCodeQuery);
                }
            });
        });
    }
    
    /**
     * Escape HTML special characters
     */
    function escapeHtml(text) {
        if (!text) return '';
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }
    
    /**
     * Navigate to a workflow and optionally locate/open an action block and highlight a search query in Monaco
     * @param {string} workflowId - ID of target workflow
     * @param {string|null} actionName - Optional name of action block to click
     * @param {string|null} searchQuery - Optional code search query to highlight
     */
    async function navigateToWorkflow(workflowId, actionName = null, searchQuery = null) {
        if (!currentProjectId || !workflowId) return;
        
        const path = `/my-projects/${currentProjectId}/workflows/${workflowId}`;
        const url = `https://studio.mekari.com${path}`;
        
        try {
            const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
            if (!activeTab) return;
            
            // Try Vue Router navigation first
            const navigated = await navigateWorkflowWithVueRouter(activeTab.id, path);
            
            if (!navigated) {
                // Fallback to direct URL navigation
                chrome.tabs.update(activeTab.id, { url });
                
                if (actionName && searchQuery) {
                    // One-time listener for hard-reloaded tab completion
                    const listener = (tabId, changeInfo) => {
                        if (tabId === activeTab.id && changeInfo.status === 'complete') {
                            chrome.tabs.onUpdated.removeListener(listener);
                            setTimeout(() => {
                                executeClickAndHighlight(activeTab.id, actionName, searchQuery);
                            }, 500);
                        }
                    };
                    chrome.tabs.onUpdated.addListener(listener);
                }
            } else if (actionName && searchQuery) {
                // Vue Router succeeded, inject immediately
                executeClickAndHighlight(activeTab.id, actionName, searchQuery);
            }
        } catch (err) {
            console.error('Side Panel: Failed to navigate to workflow:', err);
        }
    }

    /**
     * Injects a script into the page execution context to locate the block, click it, and highlight the query in Monaco
     */
    async function executeClickAndHighlight(tabId, actionName, searchQuery) {
        if (!tabId || !chrome.scripting?.executeScript) return;
        
        try {
            await chrome.scripting.executeScript({
                target: { tabId },
                world: 'MAIN',
                func: (actionName, searchQuery) => {
                    console.log('[OWE] Triggering click and highlight for action:', actionName, 'query:', searchQuery);
                    
                    const timeout = 5000;
                    const startTime = Date.now();
                    
                    function pollAndClickBlock() {
                        const blocks = Array.from(document.querySelectorAll('[data-testid="action--block-script"]'));
                        if (blocks.length === 0) {
                            if (Date.now() - startTime < timeout) {
                                setTimeout(pollAndClickBlock, 100);
                            } else {
                                console.error('[OWE] Timeout waiting for script action blocks to load');
                            }
                            return;
                        }
                        
                        let targetBlock = null;
                        if (actionName) {
                            const lowerActionName = actionName.toLowerCase();
                            targetBlock = blocks.find(block => {
                                const spans = block.querySelectorAll('span');
                                for (const span of spans) {
                                    if (span.textContent.trim().toLowerCase() === lowerActionName) {
                                        return true;
                                    }
                                }
                                return block.textContent.toLowerCase().includes(lowerActionName);
                            });
                        }
                        
                        if (!targetBlock && blocks.length > 0) {
                            targetBlock = blocks[0];
                        }
                        
                        if (targetBlock) {
                            console.log('[OWE] Found target action block:', targetBlock);
                            targetBlock.scrollIntoView({ behavior: 'smooth', block: 'center' });
                            targetBlock.click();
                            pollAndHighlightEditor();
                        } else {
                            console.error('[OWE] Target action block not found');
                        }
                    }
                    
                    const editorStartTime = Date.now();
                    function pollAndHighlightEditor() {
                        if (typeof window.monaco === 'undefined' || !window.monaco.editor) {
                            if (Date.now() - editorStartTime < timeout) {
                                setTimeout(pollAndHighlightEditor, 100);
                            } else {
                                console.error('[OWE] Timeout waiting for window.monaco to be defined');
                            }
                            return;
                        }
                        
                        const editors = window.monaco.editor.getEditors();
                        const activeEditor = editors.find(ed => {
                            const domNode = ed.getDomNode();
                            return domNode && document.body.contains(domNode);
                        });
                        
                        if (!activeEditor) {
                            if (Date.now() - editorStartTime < timeout) {
                                setTimeout(pollAndHighlightEditor, 100);
                            } else {
                                console.error('[OWE] Timeout waiting for active Monaco Editor instance');
                            }
                            return;
                        }
                        
                        console.log('[OWE] Active Monaco Editor found:', activeEditor);
                        
                        const model = activeEditor.getModel();
                        if (!model) {
                            console.error('[OWE] Monaco Editor has no model');
                            return;
                        }
                        
                        if (searchQuery) {
                            const matches = model.findMatches(searchQuery, false, false, false, null, false, 1);
                            if (matches && matches.length > 0) {
                                const range = matches[0].range;
                                console.log('[OWE] Match found in Monaco at range:', range);
                                activeEditor.setSelection(range);
                                activeEditor.revealRangeInCenter(range);
                                activeEditor.focus();
                            } else {
                                console.warn('[OWE] Search query match not found in Monaco editor content');
                            }
                        }
                    }
                    
                    pollAndClickBlock();
                },
                args: [actionName, searchQuery]
            });
        } catch (err) {
            console.error('Side Panel: Failed to execute click and highlight script:', err);
        }
    }
    
    // Code search input handler
    codeSearchInput.addEventListener('input', (e) => {
        const query = e.target.value;
        
        // Update clear button
        if (query.trim()) {
            codeSearchClear.classList.add('visible');
        } else {
            codeSearchClear.classList.remove('visible');
        }
        
        // Debounce search
        if (codeSearchDebounceTimer) {
            clearTimeout(codeSearchDebounceTimer);
        }
        codeSearchDebounceTimer = setTimeout(() => {
            performCodeSearch(query);
        }, 300);
    });
    
    // Clear button handler
    codeSearchClear.addEventListener('click', () => {
        codeSearchInput.value = '';
        codeSearchInput.focus();
        codeSearchClear.classList.remove('visible');
        codeSearchResults.innerHTML = '';
        currentCodeQuery = '';
    });
    
    // Keyboard shortcut: Escape to clear code search
    codeSearchInput.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
            codeSearchInput.value = '';
            codeSearchClear.classList.remove('visible');
            codeSearchResults.innerHTML = '';
            currentCodeQuery = '';
        }
    });
    
    // ============================================
    // END CODE SEARCH
    // ============================================

    // Manual refresh button
    const refreshBtn = document.getElementById('refresh-workflows');
    if (refreshBtn) {
        refreshBtn.addEventListener('click', async () => {
            console.log('Side Panel: Manual refresh clicked');
            refreshBtn.classList.add('spinning');
            
            try {
                const response = await chrome.runtime.sendMessage({ type: 'manual_refresh' });
                
                if (response && response.success) {
                    console.log('Side Panel: Manual refresh succeeded, fetched', response.count, 'workflows');
                } else {
                    console.warn('Side Panel: Manual refresh failed:', response?.error);
                    treeView.showNotification(response?.error || 'Refresh failed', 'warning');
                }
            } catch (err) {
                console.error('Side Panel: Manual refresh error:', err);
                treeView.showNotification('Refresh failed: ' + err.message, 'error');
            } finally {
                refreshBtn.classList.remove('spinning');
            }
        });
    }

    // Hard reset button — clear all data and re-fetch from scratch
    const hardResetBtn = document.getElementById('hard-reset-workflows');
    if (hardResetBtn) {
        hardResetBtn.addEventListener('click', async () => {
            const confirmed = confirm(
                'HARD RESET\n\n' +
                'This will:\n' +
                '\u2022 Clear all stored workflow data\n' +
                '\u2022 Reset the code search index\n' +
                '\u2022 Re-fetch ALL workflows from the server\n\n' +
                'This cannot be undone. Continue?'
            );
            if (!confirmed) return;
            
            console.log('Side Panel: Hard reset initiated');
            hardResetBtn.classList.add('spinning');
            hardResetBtn.disabled = true;
            
            try {
                const response = await chrome.runtime.sendMessage({ type: 'hard_reset' });
                
                if (response && response.success) {
                    const msg = `Hard reset complete! Fetched ${response.count} workflows, indexed ${response.indexed} into code search.`;
                    console.log('Side Panel: Hard reset succeeded:', msg);
                    treeView.showNotification(msg, 'success');
                } else {
                    console.warn('Side Panel: Hard reset failed:', response?.error);
                    treeView.showNotification(response?.error || 'Hard reset failed', 'error');
                }
            } catch (err) {
                console.error('Side Panel: Hard reset error:', err);
                treeView.showNotification('Hard reset failed: ' + err.message, 'error');
            } finally {
                hardResetBtn.classList.remove('spinning');
                hardResetBtn.disabled = false;
            }
        });
    }
    
    // Load workflow list from storage
    try {
        const result = await STORAGE_AREA.get(['workflowList', 'projectId']);
        console.log('Side Panel: Loaded from storage', result);
        
        if (result.projectId) {
            currentProjectId = result.projectId;
        }
        
        if (result.workflowList && result.workflowList.categorized) {
            const treeData = convertToTreeData(result.workflowList.categorized, currentProjectId);
            treeView.data = treeData;
            treeView.render();
        }
    } catch (err) {
        console.error('Side Panel: Failed to load workflow list', err);
    }
    
    // Listen for storage changes
    chrome.storage.onChanged.addListener((changes, areaName) => {
        if (areaName !== 'local') {
            return;
        }

        console.log('Side Panel: Storage changed', changes);
        
        if (changes.projectId) {
            currentProjectId = changes.projectId.newValue;
        }
        
        if (changes.workflowList) {
            const newList = changes.workflowList.newValue;
            if (newList && newList.categorized) {
                const reconciled = reconcileTreeData(
                    treeView.data,
                    newList.categorized,
                    currentProjectId
                );
                treeView.data = reconciled.tree;
                treeView.render();
            }
        }
    });
});
