// Background Service Worker for Officeless Web Extender

// Import SQLite client for FTS5 indexing
import { indexWorkflow, searchCode, getWorkflowCode, deleteWorkflow, clearAll } from './src/services/sqlite-client.js';

const LAST_WORKFLOW_FETCH_TIMESTAMPS = 'lastWorkflowFetchTimestamps';

chrome.runtime.onInstalled.addListener(() => {
    console.log('Officeless Web Extender service worker installed.');
});

console.log('Officeless Web Extender service worker loaded.');

// Helper function to generate random ID
function generateRandomId(length = 10) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
}

// Reconcile new workflow data with existing data

// Fetch all workflows with pagination
async function fetchAllWorkflows(companyId, projectId, authToken, lastFetchTimestamp) {
    const allWorkflows = [];
    let page = 1;
    const limit = 100;
    let hasMore = true;
    
    const sort = encodeURIComponent(JSON.stringify({ "updated_at": -1 }));
    const filter = encodeURIComponent(JSON.stringify({ 
        "company_id": parseInt(companyId), 
        "project_id": projectId 
    }));
    
    // Build headers with auth token if available
    const headers = {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
    };
    if (authToken) {
        headers['Authorization'] = authToken;
    }
    
    while (hasMore) {
        const url = `https://officeless-gateway.mekari.com/v1/nocode-workflow-setup-service/studio/automations?page=${page}&limit=${limit}&sort=${sort}&filter=${filter}`;
        
        try {
            console.log(`Background: Fetching workflows page ${page}`);
            const response = await fetch(url, {
                method: 'GET',
                credentials: 'include',
                headers: headers
            });
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const data = await response.json();
            
            if (data.data && Array.isArray(data.data)) {
                if (lastFetchTimestamp && lastFetchTimestamp > 0) {
                    // Only keep workflows updated since our last fetch
                    const newWorkflows = data.data.filter(wf => wf.updated_at >= lastFetchTimestamp);
                    allWorkflows.push(...newWorkflows);

                    // Early stop: if any workflow on this page is older than lastFetchTimestamp,
                    // subsequent pages will be entirely older (API returns sorted by updated_at: -1)
                    const hasOlderWorkflow = data.data.some(wf => (wf.updated_at || 0) < lastFetchTimestamp);
                    if (hasOlderWorkflow) {
                        hasMore = false;
                    }
                } else {
                    allWorkflows.push(...data.data);
                }
                console.log(`Background: Fetched ${data.data.length} workflows from page ${page}`);
                
                // Check if we need to fetch more
                if (data.data.length < limit) {
                    hasMore = false;
                } else {
                    page++;
                }
            } else {
                hasMore = false;
            }
        } catch (error) {
            console.error(`Background: Error fetching page ${page}:`, error);
            hasMore = false;
        }
    }
    
    console.log(`Background: Total workflows fetched: ${allWorkflows.length}`);
    return allWorkflows;
}

// Process workflows into categorized structure
function processWorkflows(workflows) {
    const processedWorkflows = workflows.map(workflow => {
        const name = workflow.name || '';
        const parts = name.split('_');
        const layer = parts[0] || 'Unknown';
        const entity = parts[1] || 'Unknown';
        const trigger = workflow.trigger || {};

        let triggerType = 'unknown';
        let triggerName = '';
        let triggerIdentifier = '';

        if (trigger.api_v2 && trigger.api_v2.url) {
            triggerType = 'api';
            triggerIdentifier = trigger.api_v2.url;
        } else if (trigger.webhook_v2 && trigger.webhook_v2.url) {
            triggerType = 'webhook';
            triggerIdentifier = trigger.webhook_v2.url;
        } else if (trigger.type === 'function') {
            triggerType = 'function';
            triggerName = trigger.function?.name || '';
        } else if (trigger.type === 'job' || trigger.type === 'dedicated_job') {
            triggerType = 'job';
            triggerName = trigger.dedicated_job?.name || trigger.job?.name || '';
        }

        return {
            id: workflow.id,
            name: name,
            layer: layer,
            entity: entity,
            triggerType,
            triggerName,
            triggerIdentifier
        };
    });
    
    // Categorize by Entity -> Layer
    const categorized = {};
    processedWorkflows.forEach(wf => {
        if (!categorized[wf.entity]) {
            categorized[wf.entity] = {};
        }
        if (!categorized[wf.entity][wf.layer]) {
            categorized[wf.entity][wf.layer] = [];
        }
        categorized[wf.entity][wf.layer].push(wf);
    });
    
    return {
        workflows: processedWorkflows,
        categorized: categorized,
        timestamp: Date.now(),
        totalCount: workflows.length
    };
}

// Request auth token from content script (which reads from localStorage via injected.js)
async function requestAuthTokenFromContent(tabId) {
    return new Promise((resolve, reject) => {
        const timeout = setTimeout(() => {
            reject(new Error('Auth token request timed out. Please refresh the page.'));
        }, 5000);
        
        chrome.tabs.sendMessage(tabId, { type: 'request_auth_token' }, (response) => {
            clearTimeout(timeout);
            if (chrome.runtime.lastError) {
                reject(new Error('Failed to communicate with page. Please ensure you are on a Studio page.'));
            } else if (response && response.success && response.token) {
                resolve(response.token);
            } else {
                reject(new Error(response?.error || 'No auth token available. Please refresh the page.'));
            }
        });
    });
}

// Get active tab that matches the Studio URL pattern

// Flatten categorized structure back into a flat workflows array
function flattenCategorizedToWorkflows(categorized) {
    const result = [];
    for (const entity of Object.keys(categorized)) {
        for (const layer of Object.keys(categorized[entity])) {
            result.push(...categorized[entity][layer]);
        }
    }
    return result.sort((a, b) => a.name.localeCompare(b.name));
}

// Returns merged categorized object
function reconcileWorkflowData(existingCategorized, newWorkflows) {
    // Start with existing data or empty object
    const merged = existingCategorized ? JSON.parse(JSON.stringify(existingCategorized)) : {};
    
    // Process new workflows and merge into existing structure
    newWorkflows.forEach(workflow => {
        const { entity, layer, id, name, triggerType, triggerName, triggerIdentifier } = workflow;
        
        // Initialize entity if not exists
        if (!merged[entity]) {
            merged[entity] = {};
        }
        
        // Initialize layer if not exists
        if (!merged[entity][layer]) {
            merged[entity][layer] = [];
        }
        
        // Check if workflow already exists (by id)
        const existingIndex = merged[entity][layer].findIndex(w => w.id === id);
        
        if (existingIndex >= 0) {
            // Update existing workflow
            merged[entity][layer][existingIndex] = { id, name, layer, entity, triggerType, triggerName, triggerIdentifier };
        } else {
            // Add new workflow
            merged[entity][layer].push({ id, name, layer, entity, triggerType, triggerName, triggerIdentifier });
        }
    });
    
    // Sort workflows within each layer
    Object.keys(merged).forEach(entity => {
        Object.keys(merged[entity]).forEach(layer => {
            merged[entity][layer].sort((a, b) => a.name.localeCompare(b.name));
        });
    });
    
    return merged;
}

async function storeWorkflowList(workflowList, projectId) {
    const existingData = await chrome.storage.local.get(['workflowList', 'projectId']);
    const existingCategorized = existingData.workflowList?.categorized || null;
    const existingProjectId = existingData.projectId || null;

    let reconciledCategorized;
    if (existingProjectId && existingProjectId !== projectId) {
        console.log('Background: Project changed, starting fresh');
        reconciledCategorized = workflowList.categorized;
    } else {
        reconciledCategorized = reconcileWorkflowData(
            existingCategorized,
            workflowList.workflows
        );
    }

    const mergedWorkflowList = {
        workflows: flattenCategorizedToWorkflows(reconciledCategorized),
        categorized: reconciledCategorized,
        timestamp: Date.now()
    };

    await chrome.storage.local.set({
        workflowList: mergedWorkflowList,
        projectId: projectId
    });

    console.log('Background: Workflow list reconciled and stored');
}

// Handle messages from content script or popup
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    (async () => {
        console.log('Background: Received message', message?.type || '(unknown)');

        if (message.type === 'fetch_all_workflows') {
            // Fetch all workflows with pagination (smart incremental)
            try {
                const { companyId, projectId, maxUpdatedAt = 0 } = message.data;
                const tabId = sender.tab?.id;
                
                if (!tabId) {
                    sendResponse({ success: false, error: 'No tab ID available' });
                    return;
                }
                
                // Request auth token from content script
                let authToken;
                try {
                    authToken = await requestAuthTokenFromContent(tabId);
                } catch (err) {
                    console.error('Background: Failed to get auth token:', err);
                    sendResponse({ success: false, error: err.message });
                    return;
                }
                
                // Read stored timestamps map for conditional fetch decision
                const stored = await chrome.storage.local.get([LAST_WORKFLOW_FETCH_TIMESTAMPS]);
                const timestampsMap = stored[LAST_WORKFLOW_FETCH_TIMESTAMPS] || {};
                const lastFetchTimestamp = timestampsMap[projectId] || 0;
                
                let workflows = [];
                let fetchSkipped = false;
                
                if (lastFetchTimestamp === 0) {
                    // First fetch for this project — get everything
                    console.log('Background: First fetch for project', projectId, '- fetching all workflows');
                    workflows = await fetchAllWorkflows(companyId, projectId, authToken, 0);
                } else if (maxUpdatedAt > lastFetchTimestamp) {
                    // Newer workflows exist — fetch updated ones with early stop
                    console.log('Background: Project', projectId, 'has changes - fetching incrementally');
                    workflows = await fetchAllWorkflows(companyId, projectId, authToken, lastFetchTimestamp);
                } else {
                    // Up to date — no full fetch needed
                    console.log('Background: Project', projectId, 'is up to date, skipping full fetch');
                    fetchSkipped = true;
                }
                
                if (!fetchSkipped) {
                    const processed = processWorkflows(workflows);
                    
                    // Store with reconciliation
                    await storeWorkflowList(processed, projectId);
                    
                    // Index each workflow for FTS5 search
                    for (const workflow of workflows) {
                        try {
                            await indexWorkflow(workflow);
                        } catch (indexErr) {
                            // Silently skip workflows that fail to index
                        }
                    }
                    
                    // Update the stored timestamp for this project
                    const newMaxUpdatedAt = workflows.length > 0
                        ? Math.max(...workflows.map(w => w.updated_at || 0), maxUpdatedAt)
                        : maxUpdatedAt;
                    if (newMaxUpdatedAt > 0) {
                        timestampsMap[projectId] = newMaxUpdatedAt;
                        await chrome.storage.local.set({ [LAST_WORKFLOW_FETCH_TIMESTAMPS]: timestampsMap });
                        console.log('Background: Updated lastWorkflowFetchTimestamps for project', projectId, 'to', newMaxUpdatedAt);
                    }
                }
                
                sendResponse({ success: true, count: workflows.length, skipped: fetchSkipped });
            } catch (error) {
                console.error('Background: Failed to fetch workflows', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'store_workflow_list') {
            // Store workflow list with reconciliation
            try {
                const newProjectId = message.data.projectId;

                await storeWorkflowList(message.data.workflowList, newProjectId);
                sendResponse({ success: true, reconciled: true });
            } catch (error) {
                console.error('Background: Failed to store workflow list', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'open_sidepanel') {
            // Open from content script - we have sender.tab
            try {
                await chrome.sidePanel.open({ windowId: sender.tab.windowId });
                
                // If there's workflow data, store it for the side panel to retrieve
                if (message.data) {
                    await chrome.storage.local.set({ 
                        workflowData: message.data,
                        sourceTabId: sender.tab.id
                    });
                }
                
                sendResponse({ success: true });
            } catch (error) {
                console.error('Failed to open side panel:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'open_sidepanel_from_popup') {
            // Open from popup - need to get current active tab
            try {
                const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
                
                if (!activeTab) {
                    sendResponse({ success: false, error: 'No active tab found' });
                    return;
                }
                
                await chrome.sidePanel.open({ windowId: activeTab.windowId });
                
                // Store the active tab ID for reference
                await chrome.storage.local.set({ 
                    sourceTabId: activeTab.id
                });
                
                sendResponse({ success: true });
            } catch (error) {
                console.error('Failed to open side panel from popup:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'manual_refresh') {
            // Manual refresh triggered from sidepanel
            try {
                const stored = await chrome.storage.local.get(['workflowFetchContext']);
                const context = stored.workflowFetchContext;
                
                if (!context || !context.companyId || !context.projectId) {
                    sendResponse({ success: false, error: 'No project context found. Navigate to a workflow in Studio first.' });
                    return;
                }
                
                // Find active tab on Studio domain
                const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
                if (!activeTab || !activeTab.url || !activeTab.url.includes('studio.mekari.com')) {
                    sendResponse({ success: false, error: 'Please navigate to a Studio page and try again.' });
                    return;
                }
                
                // Request auth token from content script
                let authToken;
                try {
                    authToken = await requestAuthTokenFromContent(activeTab.id);
                } catch (err) {
                    console.error('Background: Failed to get auth token for manual refresh:', err);
                    sendResponse({ success: false, error: err.message });
                    return;
                }
                
                console.log('Background: Manual refresh triggered with context:', context.companyId, context.projectId);

                // Read stored timestamp for smart pagination
                const tsData = await chrome.storage.local.get([LAST_WORKFLOW_FETCH_TIMESTAMPS]);
                const timestampsMap = tsData[LAST_WORKFLOW_FETCH_TIMESTAMPS] || {};
                const lastFetchTimestamp = timestampsMap[context.projectId] || 0;

                // fetchAllWorkflows uses lastFetchTimestamp for early-stop internally
                const workflows = await fetchAllWorkflows(context.companyId, context.projectId, authToken, lastFetchTimestamp);
                const processed = processWorkflows(workflows);
                
                await storeWorkflowList(processed, context.projectId);

                // Index each workflow for FTS5 search
                for (const workflow of workflows) {
                    try {
                        await indexWorkflow(workflow);
                    } catch (indexErr) {
                        // Silently skip workflows that fail to index
                    }
                }

                // Update timestamp map for this project
                if (workflows.length > 0) {
                    const newMaxUpdatedAt = Math.max(...workflows.map(w => w.updated_at || 0));
                    timestampsMap[context.projectId] = newMaxUpdatedAt;
                    await chrome.storage.local.set({ [LAST_WORKFLOW_FETCH_TIMESTAMPS]: timestampsMap });
                    console.log('Background: Updated lastWorkflowFetchTimestamps for project', context.projectId, 'to', newMaxUpdatedAt);
                }
                
                sendResponse({ success: true, count: workflows.length });
            } catch (error) {
                console.error('Background: Manual refresh failed', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'hard_reset') {
            // Hard reset — clear all storage, drop SQLite tables, re-fetch everything
            try {
                const stored = await chrome.storage.local.get(['workflowFetchContext']);
                const context = stored.workflowFetchContext;
                
                if (!context || !context.companyId || !context.projectId) {
                    sendResponse({ success: false, error: 'No project context found. Navigate to a workflow in Studio first.' });
                    return;
                }
                
                // Find active tab on Studio domain
                const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
                if (!activeTab || !activeTab.url || !activeTab.url.includes('studio.mekari.com')) {
                    sendResponse({ success: false, error: 'Please navigate to a Studio page and try again.' });
                    return;
                }
                
                // Request auth token from content script
                let authToken;
                try {
                    authToken = await requestAuthTokenFromContent(activeTab.id);
                } catch (err) {
                    console.error('Background: Failed to get auth token for hard reset:', err);
                    sendResponse({ success: false, error: err.message });
                    return;
                }
                
                console.log('Background: Hard reset triggered — clearing all data and re-fetching');
                
                // Step 1: Clear SQLite database (drop + recreate tables)
                await clearAll();
                console.log('Background: SQLite database cleared');
                
                // Step 2: Clear chrome.storage.local workflow data
                await chrome.storage.local.remove([
                    'workflowList',
                    LAST_WORKFLOW_FETCH_TIMESTAMPS
                ]);
                console.log('Background: Storage cleared');
                
                // Step 3: Hard fetch ALL workflows (lastFetchTimestamp=0 forces full fetch, no early-stop)
                const workflows = await fetchAllWorkflows(context.companyId, context.projectId, authToken, 0);
                console.log('Background: Hard reset fetched', workflows.length, 'workflows');
                
                // Step 4: Process and store workflow list
                const processed = processWorkflows(workflows);
                await storeWorkflowList(processed, context.projectId);
                
                // Step 5: Re-index every workflow into SQLite
                let indexedCount = 0;
                let indexFailures = 0;
                for (const workflow of workflows) {
                    try {
                        await indexWorkflow(workflow);
                        indexedCount++;
                    } catch (indexErr) {
                        indexFailures++;
                    }
                }
                console.log('Background: Hard reset indexed', indexedCount, 'workflows,', indexFailures, 'failures');
                
                // Step 6: Update fetch timestamp for this project
                if (workflows.length > 0) {
                    const newMaxUpdatedAt = Math.max(...workflows.map(w => w.updated_at || 0));
                    const timestampsMap = { [context.projectId]: newMaxUpdatedAt };
                    await chrome.storage.local.set({ [LAST_WORKFLOW_FETCH_TIMESTAMPS]: timestampsMap });
                    console.log('Background: Hard reset updated timestamp for project', context.projectId, 'to', newMaxUpdatedAt);
                }
                
                sendResponse({ 
                    success: true, 
                    count: workflows.length, 
                    indexed: indexedCount, 
                    indexFailures 
                });
            } catch (error) {
                console.error('Background: Hard reset failed', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'duplicate_workflow') {
            // Duplicate a workflow
            try {
                const { workflowId } = message.data;
                
                if (!workflowId) {
                    sendResponse({ success: false, error: 'No workflow ID provided' });
                    return;
                }
                
                const stored = await chrome.storage.local.get(['sourceTabId']);

                // Find a valid tab to request auth token from
                let sourceTabId = stored.sourceTabId;
                if (!sourceTabId) {
                    const [activeTab] = await chrome.tabs.query({ active: true, currentWindow: true });
                    sourceTabId = activeTab?.id;
                }
                
                if (!sourceTabId) {
                    sendResponse({ success: false, error: 'No valid tab found. Please navigate to a Studio page.' });
                    return;
                }
                
                // Request auth token from content script
                let authToken;
                try {
                    authToken = await requestAuthTokenFromContent(sourceTabId);
                } catch (err) {
                    sendResponse({ success: false, error: err.message });
                    return;
                }
                
                // Fetch the workflow JSON from API (avoid storing large payloads locally)
                const filter = encodeURIComponent(JSON.stringify({ id: [workflowId] }));
                const workflowResponse = await fetch(
                    `https://officeless-gateway.mekari.com/v1/nocode-workflow-setup-service/studio/automations?limit=1&page=1&filter=${filter}`,
                    {
                        method: 'GET',
                        credentials: 'include',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json',
                            'Authorization': authToken
                        }
                    }
                );
                
                if (!workflowResponse.ok) {
                    const errorText = await workflowResponse.text();
                    throw new Error(`HTTP error! status: ${workflowResponse.status}, body: ${errorText}`);
                }
                
                const workflowResult = await workflowResponse.json();
                const dataArray = Array.isArray(workflowResult?.data) ? workflowResult.data : [];
                const originalData = dataArray[0];
                if (!originalData) {
                    throw new Error('Workflow data not found in API response');
                }
                
                // Deep clone the workflow data
                const duplicatedWorkflow = JSON.parse(JSON.stringify(originalData));
                
                // Remove the id field
                delete duplicatedWorkflow.id;
                
                // Append "copy" to unique constrained fields
                if (duplicatedWorkflow.name) {
                    duplicatedWorkflow.name = duplicatedWorkflow.name + ' copy';
                }
                
                // Helper function to append "copy" to a nested field if it exists
                const appendCopyToField = (obj, path) => {
                    const parts = path.split('.');
                    let current = obj;
                    for (let i = 0; i < parts.length - 1; i++) {
                        if (current[parts[i]] === undefined) return;
                        current = current[parts[i]];
                    }
                    const lastKey = parts[parts.length - 1];
                    if (current[lastKey]) {
                        current[lastKey] = current[lastKey] + ' copy';
                    }
                };
                
                // Append "copy" to trigger fields
                if (duplicatedWorkflow.trigger) {
                    appendCopyToField(duplicatedWorkflow, 'trigger.api_v2.url');
                    appendCopyToField(duplicatedWorkflow, 'trigger.function.name');
                    appendCopyToField(duplicatedWorkflow, 'trigger.job.name');
                    appendCopyToField(duplicatedWorkflow, 'trigger.dedicated_job.name');
                    appendCopyToField(duplicatedWorkflow, 'trigger.webhook_v2.url');
                    appendCopyToField(duplicatedWorkflow, 'trigger.form_interaction_function.name');
		            appendCopyToField(duplicatedWorkflow, 'trigger.block_name');
                }



                const randomString = () => Math.random().toString(36).slice(2);

                const recursiveBlockNameFill = (listOfActions) => {
                    // Guard clause: Ensure listOfActions exists and is an array
                    if (!Array.isArray(listOfActions) || listOfActions.length === 0) return;

                    listOfActions.forEach(action => {
                        // Safely assign a random string if block_name is missing, empty, or null
                        if (!action.block_name) {
                            action.block_name = randomString();
                        }

                        // Handle conditional blocks safely
                        if (action.type === "conditional") {
                            if (action.action_true?.length) recursiveBlockNameFill(action.action_true);
                            if (action.action_false?.length) recursiveBlockNameFill(action.action_false);
                        }

                        // Handle while blocks safely (Double check your API structure here!)
                        if (action.type === "while") {
                            if (action.while?.action_while?.length) recursiveBlockNameFill(action.while.action_while);
                            if (action.while?.action_done?.length) recursiveBlockNameFill(action.while.action_done);
                        }
                    });
                };     

                recursiveBlockNameFill(duplicatedWorkflow.actions);

                console.log('Background: Duplicating workflow:', { original: originalData.name, duplicated: duplicatedWorkflow.name });
                
                // POST to the API
                const response = await fetch('https://officeless-gateway.mekari.com/v1/nocode-workflow-setup-service/studio/automations', {
                    method: 'POST',
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json',
                        'Authorization': authToken
                    },
                    body: JSON.stringify(duplicatedWorkflow)
                });
                
                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`HTTP error! status: ${response.status}, body: ${errorText}`);
                }
                
                const result = await response.json();
                console.log('Background: Workflow duplicated successfully:', result);
                
                const newWorkflowId = result.data?.id;
                const projectId = originalData.project_id;
                
                sendResponse({ 
                    success: true, 
                    data: result,
                    newWorkflowId,
                    projectId
                });
            } catch (error) {
                console.error('Background: Failed to duplicate workflow:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'create_wrapper_workflow') {
            // Create wrapper workflow for function/job execution
            try {
                const { config } = message.data;
                const tabId = sender.tab?.id;
                
                if (!tabId) {
                    sendResponse({ success: false, error: 'No tab ID available. Please try again from a Studio page.' });
                    return;
                }
                
                // Request auth token from content script
                let authToken;
                try {
                    authToken = await requestAuthTokenFromContent(tabId);
                } catch (err) {
                    sendResponse({ success: false, error: err.message });
                    return;
                }
                
                const projectId = config.projectId;
                const userCompanyId = config.companyId;
                if (!projectId || !userCompanyId) {
                    sendResponse({ success: false, error: 'Missing project or company context. Please refresh the page.' });
                    return;
                }
                
                const randomId = generateRandomId(10);
                const isFunction = config.type === 'function';
                
                const wrapperWorkflow = {
                    name: `OWE_temp_wrapper_${randomId}`,
                    description: "-",
                    disable_run_history: false,
                    is_active: true,
                    is_deleted: false,
                    is_stored_to_eventsam: true,
                    is_sync: false,
                    project_id: projectId,
                    user_company_id: userCompanyId,
                    version: 3,
                    trigger: isFunction ? {
                        type: "api_v2",
                        block_name: "API call 1",
                        container_response: "res",
                        container_variable: "req",
                        api_v2: {
                            url: randomId,
                            method: "post",
                            max_length_char_payload: 0,
                            rate_limit: 0
                        }
                    } : {
                        type: "webhook_v2",
                        block_name: "Webhook 1",
                        container_response: "res",
                        container_variable: "req",
                        webhook_v2: {
                            url: randomId,
                            method: "post",
                            max_length_char_payload: 0,
                            rate_limit: 0
                        }
                    },
                    actions: isFunction ? [
                        {
                            approval_flow: null,
                            block_name: "Call function 1",
                            compress_file_base64: null,
                            compress_file_company_drive: null,
                            compress_file_multiple_url: null,
                            conditional: { action_false: null, action_true: null, query: "" },
                            container_variable: "res",
                            custom_response: null,
                            data: null,
                            data_connection: { connection: "", do: "", query: "" },
                            dedicated_job: { counter_variable: "", input: "", name: "" },
                            external_api: { body: "", header: null, method: "", url: "" },
                            filter: null,
                            filter_v2: null,
                            form_data: null,
                            form_data_id: "",
                            function: { input: "req.body", name: config.functionName },
                            is_async: false,
                            is_auto_generated_file_url: null,
                            is_disable: false,
                            is_disable_log: false,
                            javascript: "",
                            job: { input: "", name: "" },
                            limit: "",
                            new_filter: null,
                            page: "",
                            plugin_api: null,
                            qontak_send_whatsapp: null,
                            redirect_page: null,
                            return_message: null,
                            send_notification: { apps: "", content: "", heading: "", is_custom_redirect: false, script_redirect: "", type: "", user_company_ids: "", variable_redirect: "" },
                            sort: null,
                            sum_formdata: { column: "", filter: null },
                            tablegroup_id: "",
                            talenta_get_attendances: null,
                            timeout_millisecond: 0,
                            type: "function",
                            while: { action_done: null, action_while: null, variable_source: "" }
                        }
                    ] : [
                        {
                            approval_flow: null,
                            block_name: "Dedicated job 1",
                            compress_file_base64: null,
                            compress_file_company_drive: null,
                            compress_file_multiple_url: null,
                            conditional: { action_false: null, action_true: null, query: "" },
                            container_variable: "",
                            custom_response: null,
                            data: null,
                            data_connection: { connection: "", do: "", query: "" },
                            dedicated_job: { counter_variable: "res", input: "req.body", name: config.jobName },
                            external_api: { body: "", header: null, method: "", url: "" },
                            filter: null,
                            filter_v2: null,
                            form_data: null,
                            form_data_id: "",
                            function: { input: "", name: "" },
                            is_async: true,
                            is_auto_generated_file_url: null,
                            is_disable: false,
                            is_disable_log: false,
                            javascript: "",
                            job: { input: "", name: "" },
                            limit: "",
                            new_filter: null,
                            page: "",
                            plugin_api: null,
                            qontak_send_whatsapp: null,
                            redirect_page: null,
                            return_message: null,
                            send_notification: { apps: "", content: "", heading: "", is_custom_redirect: false, script_redirect: "", type: "", user_company_ids: "", variable_redirect: "" },
                            sort: null,
                            sum_formdata: { column: "", filter: null },
                            tablegroup_id: "",
                            talenta_get_attendances: null,
                            timeout_millisecond: 0,
                            type: "dedicated_job",
                            while: { action_done: null, action_while: null, variable_source: "" }
                        }
                    ]
                };

                const response = await fetch(
                    'https://officeless-gateway.mekari.com/v1/nocode-workflow-setup-service/studio/automations',
                    {
                        method: 'POST',
                        credentials: 'include',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json',
                            'Authorization': authToken
                        },
                        body: JSON.stringify(wrapperWorkflow)
                    }
                );

                if (!response.ok) {
                    throw new Error(`Failed to create wrapper workflow: ${response.status}`);
                }

                const result = await response.json();
                const createdWorkflow = result.data;
                
                sendResponse({
                    success: true,
                    data: {
                        id: createdWorkflow.id,
                        name: createdWorkflow.name,
                        url: isFunction ? createdWorkflow.trigger.api_v2.url : createdWorkflow.trigger.webhook_v2.url
                    }
                });
            } catch (error) {
                console.error('Background: Failed to create wrapper workflow:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'delete_workflow') {
            // Delete a workflow
            try {
                const { workflowId } = message.data;
                const tabId = sender.tab?.id;
                
                if (!tabId) {
                    sendResponse({ success: false, error: 'No tab ID available. Please try again from a Studio page.' });
                    return;
                }
                
                // Request auth token from content script
                let authToken;
                try {
                    authToken = await requestAuthTokenFromContent(tabId);
                } catch (err) {
                    sendResponse({ success: false, error: err.message });
                    return;
                }
                
                const response = await fetch(
                    `https://officeless-gateway.mekari.com/v1/nocode-workflow-setup-service/studio/automations/${workflowId}`,
                    {
                        method: 'DELETE',
                        credentials: 'include',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json',
                            'Authorization': authToken
                        }
                    }
                );

                const data = await response.json();
                
                if (response.ok && !data.error && data.data === true) {
                    console.log('Background: Wrapper workflow deleted successfully');
                    sendResponse({ success: true });
                } else {
                    console.error('Background: Failed to delete wrapper workflow:', data);
                    sendResponse({ success: false, error: data.error || 'Delete failed' });
                }
            } catch (error) {
                console.error('Background: Failed to delete workflow:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'search_code') {
            // Search JavaScript code using FTS5
            try {
                const { query, options } = message;
                const results = await searchCode(query, options);
                sendResponse({ success: true, results });
            } catch (error) {
                console.error('Background: Failed to search code:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'index_workflow') {
            // Index a single workflow
            try {
                const { workflowJson } = message;
                const result = await indexWorkflow(workflowJson);
                sendResponse({ success: true, result });
            } catch (error) {
                console.error('Background: Failed to index workflow:', error);
                sendResponse({ success: false, error: error.message });
            }
        } else if (message.type === 'get_workflow_code') {
            // Get all code blocks for a workflow
            try {
                const { workflowId } = message;
                const code = await getWorkflowCode(workflowId);
                sendResponse({ success: true, code });
            } catch (error) {
                console.error('Background: Failed to get workflow code:', error);
                sendResponse({ success: false, error: error.message });
            }
        }
    })();
    
    // Return true to indicate we will send a response asynchronously
    return true;
});

// Optional: Configure side panel behavior
if (chrome.sidePanel?.setPanelBehavior) {
    chrome.sidePanel.setPanelBehavior({
        openPanelOnActionClick: false // Don't open on extension icon click (we'll control it manually via popup)
    }).catch((error) => {
        console.error('Error setting panel behavior:', error);
    });
} else {
    console.warn('Background: sidePanel API not available in this browser context.');
}

// Regex to match https://studio.mekari.com/my-projects/:project-id
const ALLOWED_PATTERN = /^https:\/\/studio\.mekari\.com\/my-projects\/[^/]+(?:\/|$)/;

// Listen for tab URL changes
chrome.tabs.onUpdated.addListener(async (tabId, info, tab) => {
    if (!tab.url) return;

    if (ALLOWED_PATTERN.test(tab.url)) {
        // Enable the side panel for THIS tab
        await chrome.sidePanel.setOptions({
            tabId,
            path: 'sidepanel.html',
            enabled: true
        });
        chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true });
    } else {
        // Disable it for any other tab/URL
        await chrome.sidePanel.setOptions({
            tabId,
            enabled: false
        });
    }
});

// Listen for tab activation (switching between tabs)
chrome.tabs.onActivated.addListener(async (activeInfo) => {
    const tabId = activeInfo.tabId;
    
    try {
        const tab = await chrome.tabs.get(tabId);
        if (!tab.url || !ALLOWED_PATTERN.test(tab.url)) {
            // Close side panel when switching to a disallowed tab
            await chrome.sidePanel.close({ windowId: tab.windowId });
        }
    } catch (err) {
        console.error('Error handling tab activation:', err);
    }
});
