/**
 * DCI Control Center v1.0 - JavaScript Controller
 * Real-time management of all crawler processes
 */

const DCI = {
    // Configuration
    sseUrl: '',
    eventSource: null,
    reconnectAttempts: 0,
    maxReconnectAttempts: 10,
    reconnectDelay: 2000,
    autoScroll: true,
    modeFilter: 'all',
    statusFilter: 'all',

    // Data storage
    processes: [],
    recentProcesses: [],
    domainLeaderboard: [],
    activityLog: [],
    poolStats: {},
    totals: {},
    modes: {},
    alerts: [],

    // Charts
    modeChart: null,
    velocityChart: null,
    pyramidChart: null,
    velocityData: [],
    maxVelocityPoints: 30,
    levelStats: {},
    networkStats: {},

    /**
     * Initialize the DCI Controller
     */
    init: function(sseUrl) {
        this.sseUrl = sseUrl;
        this.initCharts();
        this.connectSSE();
        this.loadConfig();
        console.log('[DCI] Control Center initialized');
    },

    /**
     * Connect to SSE stream
     */
    connectSSE: function() {
        if (this.eventSource) {
            this.eventSource.close();
        }

        this.updateConnectionStatus('connecting');

        this.eventSource = new EventSource(this.sseUrl);

        this.eventSource.onopen = () => {
            console.log('[DCI] SSE connected');
            this.reconnectAttempts = 0;
            this.updateConnectionStatus('connected');
        };

        this.eventSource.onmessage = (event) => {
            try {
                const data = JSON.parse(event.data);
                this.handleData(data);
            } catch (e) {
                console.error('[DCI] Error parsing SSE data:', e);
            }
        };

        this.eventSource.onerror = (error) => {
            console.error('[DCI] SSE error:', error);
            this.updateConnectionStatus('disconnected');
            this.eventSource.close();
            this.scheduleReconnect();
        };
    },

    /**
     * Schedule reconnection attempt
     */
    scheduleReconnect: function() {
        if (this.reconnectAttempts >= this.maxReconnectAttempts) {
            console.error('[DCI] Max reconnection attempts reached');
            return;
        }

        this.reconnectAttempts++;
        const delay = this.reconnectDelay * Math.pow(1.5, this.reconnectAttempts - 1);
        console.log(`[DCI] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);

        setTimeout(() => this.connectSSE(), delay);
    },

    /**
     * Update connection status indicator
     */
    updateConnectionStatus: function(status) {
        const el = document.getElementById('connectionStatus');
        if (!el) return;

        el.className = 'connection-status ' + status;
        const textEl = el.querySelector('.status-text');

        switch (status) {
            case 'connecting':
                textEl.textContent = 'Connecting...';
                break;
            case 'connected':
                textEl.textContent = 'Live';
                break;
            case 'disconnected':
                textEl.textContent = 'Disconnected';
                break;
        }
    },

    /**
     * Handle incoming SSE data
     */
    handleData: function(data) {
        // Store data
        this.processes = data.processes || [];
        this.recentProcesses = data.recent || [];
        this.totals = data.totals || {};
        this.modes = data.modes || {};
        this.poolStats = data.pool || {};
        this.domainLeaderboard = data.domain_leaderboard || [];
        this.activityLog = data.activity_log || [];
        this.alerts = data.alerts || [];
        this.levelStats = data.level_stats || {};
        this.networkStats = data.network || {};

        // Update UI
        this.updateStats();
        this.updateProcessesTable();
        this.updateLeaderboard();
        this.updateActivityLog();
        this.updateRecentList();
        this.updateAlerts();
        this.updateCharts();
        this.updateNetworkStats();

        // Update pool modal if open
        if (document.getElementById('poolModal').classList.contains('active')) {
            this.updatePoolStats();
        }
    },

    /**
     * Update global stats
     */
    updateStats: function() {
        document.getElementById('statTotal').textContent = this.formatNumber(this.totals.total_processes || 0);
        document.getElementById('statRunning').textContent = this.formatNumber(this.totals.running || 0);
        document.getElementById('statPaused').textContent = this.formatNumber(this.totals.paused || 0);
        document.getElementById('statPool').textContent = this.formatNumber(this.totals.pool_size || 0);
        document.getElementById('statImports').textContent = this.formatNumber(this.totals.imported || 0);
        document.getElementById('statErrors').textContent = this.formatNumber(this.totals.errors || 0);
        document.getElementById('statRate').textContent = this.formatNumber(Math.round(this.totals.rate || 0));
    },

    /**
     * Update processes table
     */
    updateProcessesTable: function() {
        const tbody = document.getElementById('processesTable');
        if (!tbody) return;

        // Filter processes
        let filtered = this.processes.filter(p => {
            if (this.modeFilter !== 'all' && p.mode !== this.modeFilter) return false;
            if (this.statusFilter !== 'all' && p.status !== this.statusFilter) return false;
            return true;
        });

        if (filtered.length === 0) {
            tbody.innerHTML = '<tr class="loading-row"><td colspan="10">No active processes</td></tr>';
            return;
        }

        let html = '';
        filtered.forEach(p => {
            const isSuspectedDead = p.suspected_dead;
            const rowClass = isSuspectedDead ? 'suspected-dead' : '';

            html += `
                <tr class="${rowClass}" data-process-id="${p.id}">
                    <td>
                        <span class="process-id" onclick="DCI.showProcessDetails('${p.id}')" title="Click for details">
                            ${p.id.substring(0, 8)}...
                        </span>
                    </td>
                    <td>
                        <span class="mode-badge mode-${p.mode}">${p.mode}</span>
                    </td>
                    <td>
                        <span class="status-badge status-${p.status}">
                            <span class="status-dot"></span>
                            ${p.status.toUpperCase()}
                            ${isSuspectedDead ? ' (Dead?)' : ''}
                        </span>
                    </td>
                    <td title="${p.keywords_preview}">${this.truncate(p.keywords_preview, 30)}</td>
                    <td class="number-format">${this.formatNumber(p.pool_size)}</td>
                    <td class="number-format text-success">${this.formatNumber(p.imported)}</td>
                    <td class="number-format text-danger">${this.formatNumber(p.errors)}</td>
                    <td class="number-format">${this.formatNumber(Math.round(p.rate || 0))}/min</td>
                    <td class="text-muted">${this.formatElapsed(p.elapsed)}</td>
                    <td>
                        <div class="process-actions">
                            ${p.status === 'running' ?
                                `<button class="btn-pause" onclick="DCI.controlProcess('${p.id}', 'pause')" title="Pause">&#10074;&#10074;</button>` :
                                ''}
                            ${p.status === 'paused' ?
                                `<button class="btn-resume" onclick="DCI.controlProcess('${p.id}', 'resume')" title="Resume">&#9654;</button>` :
                                ''}
                            ${p.status !== 'stopped' && p.status !== 'dead' ?
                                `<button class="btn-stop" onclick="DCI.controlProcess('${p.id}', 'stop')" title="Stop">&#9632;</button>` :
                                ''}
                        </div>
                    </td>
                </tr>
            `;
        });

        tbody.innerHTML = html;
    },

    /**
     * Update domain leaderboard
     */
    updateLeaderboard: function() {
        const container = document.getElementById('leaderboardList');
        const countBadge = document.getElementById('domainCount');
        if (!container) return;

        if (countBadge) {
            countBadge.textContent = this.domainLeaderboard.length;
        }

        if (this.domainLeaderboard.length === 0) {
            container.innerHTML = '<div class="loading">No domain data yet</div>';
            return;
        }

        let html = '';
        this.domainLeaderboard.slice(0, 30).forEach((d, i) => {
            const rankClass = i < 3 ? 'top-3' : '';
            html += `
                <div class="leaderboard-item">
                    <span class="leaderboard-rank ${rankClass}">#${i + 1}</span>
                    <span class="leaderboard-domain" title="${d.domain}">${d.domain}</span>
                    <div class="leaderboard-stats">
                        <span class="leaderboard-stat imports">${this.formatNumber(d.imported)}</span>
                        <span class="leaderboard-stat">${this.formatNumber(d.crawled)} crawled</span>
                    </div>
                </div>
            `;
        });

        container.innerHTML = html;
    },

    /**
     * Update activity log
     */
    updateActivityLog: function() {
        const container = document.getElementById('activityLog');
        if (!container) return;

        if (this.activityLog.length === 0) {
            container.innerHTML = '<div class="loading">No activity yet</div>';
            return;
        }

        let html = '';
        this.activityLog.forEach(entry => {
            const time = entry.created_at ? new Date(entry.created_at).toLocaleTimeString() : '';
            const statusClass = entry.status === 'imported' ? 'imported' :
                               (entry.status === 'error' ? 'error' : 'skipped');
            const modeClass = entry.mode ? `mode-${entry.mode}` : '';

            html += `
                <div class="activity-entry">
                    <span class="activity-time">${time}</span>
                    ${entry.mode ? `<span class="activity-mode ${modeClass}">${entry.mode}</span>` : ''}
                    <span class="activity-url" title="${entry.url}">${this.truncate(entry.url, 60)}</span>
                    <span class="activity-status ${statusClass}">${entry.status}</span>
                </div>
            `;
        });

        container.innerHTML = html;

        // Auto-scroll to bottom
        if (this.autoScroll) {
            container.scrollTop = container.scrollHeight;
        }
    },

    /**
     * Update recent processes list
     */
    updateRecentList: function() {
        const container = document.getElementById('recentList');
        if (!container) return;

        if (this.recentProcesses.length === 0) {
            container.innerHTML = '<div class="loading">No recent processes</div>';
            return;
        }

        let html = '';
        this.recentProcesses.forEach(p => {
            const stoppedTime = p.stopped_at ? new Date(p.stopped_at).toLocaleString() : 'Unknown';

            html += `
                <div class="recent-item">
                    <span class="recent-mode">
                        <span class="mode-badge mode-${p.mode}">${p.mode}</span>
                    </span>
                    <span class="recent-status">
                        <span class="status-badge status-${p.status}">
                            <span class="status-dot"></span>
                            ${p.status.toUpperCase()}
                        </span>
                    </span>
                    <div class="recent-stats">
                        <span><strong>${this.formatNumber(p.imported)}</strong> imported</span>
                        <span><strong>${this.formatNumber(p.processed)}</strong> processed</span>
                        <span class="text-danger"><strong>${this.formatNumber(p.errors)}</strong> errors</span>
                    </div>
                    <span class="recent-time">${stoppedTime}</span>
                </div>
            `;
        });

        container.innerHTML = html;
    },

    /**
     * Update alerts banner
     */
    updateAlerts: function() {
        const banner = document.getElementById('alertsBanner');
        const content = document.getElementById('alertsContent');
        if (!banner || !content) return;

        if (this.alerts.length === 0) {
            banner.style.display = 'none';
            return;
        }

        banner.style.display = 'block';

        let html = '';
        this.alerts.forEach(alert => {
            html += `
                <div class="alert-item ${alert.alert_type}">
                    <span>${alert.message}</span>
                    <button class="alert-dismiss" onclick="DCI.acknowledgeAlert(${alert.id})">&times;</button>
                </div>
            `;
        });

        content.innerHTML = html;
    },

    /**
     * Initialize Charts
     */
    initCharts: function() {
        // Mode Distribution Chart
        const modeCtx = document.getElementById('modeChart');
        if (modeCtx) {
            this.modeChart = new Chart(modeCtx, {
                type: 'doughnut',
                data: {
                    labels: ['Viral', 'Ultimate', 'Multi', 'Infinite', 'Other'],
                    datasets: [{
                        data: [0, 0, 0, 0, 0],
                        backgroundColor: [
                            '#8957e5',
                            '#1f6feb',
                            '#238636',
                            '#f0883e',
                            '#6e7681'
                        ],
                        borderWidth: 0
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    plugins: {
                        legend: {
                            position: 'right',
                            labels: {
                                color: '#c9d1d9',
                                font: { size: 11 }
                            }
                        }
                    }
                }
            });
        }

        // Velocity Chart
        const velocityCtx = document.getElementById('velocityChart');
        if (velocityCtx) {
            this.velocityChart = new Chart(velocityCtx, {
                type: 'line',
                data: {
                    labels: [],
                    datasets: [{
                        label: 'Imports/min',
                        data: [],
                        borderColor: '#3fb950',
                        backgroundColor: 'rgba(63, 185, 80, 0.1)',
                        fill: true,
                        tension: 0.3,
                        pointRadius: 2
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        x: {
                            display: true,
                            grid: { color: '#21262d' },
                            ticks: { color: '#8b949e', font: { size: 10 } }
                        },
                        y: {
                            display: true,
                            beginAtZero: true,
                            grid: { color: '#21262d' },
                            ticks: { color: '#8b949e', font: { size: 10 } }
                        }
                    },
                    plugins: {
                        legend: {
                            display: false
                        }
                    }
                }
            });
        }

        // Pyramid Levels Chart
        const pyramidCtx = document.getElementById('pyramidChart');
        if (pyramidCtx) {
            this.pyramidChart = new Chart(pyramidCtx, {
                type: 'bar',
                data: {
                    labels: [],
                    datasets: [{
                        label: 'URLs at Level',
                        data: [],
                        backgroundColor: 'rgba(137, 87, 229, 0.7)',
                        borderColor: '#8957e5',
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    indexAxis: 'y',
                    scales: {
                        x: {
                            display: true,
                            beginAtZero: true,
                            grid: { color: '#21262d' },
                            ticks: { color: '#8b949e', font: { size: 10 } }
                        },
                        y: {
                            display: true,
                            grid: { color: '#21262d' },
                            ticks: { color: '#8b949e', font: { size: 10 } }
                        }
                    },
                    plugins: {
                        legend: { display: false }
                    }
                }
            });
        }
    },

    /**
     * Update Charts
     */
    updateCharts: function() {
        // Update Mode Chart
        if (this.modeChart) {
            const modes = this.modes;
            const other = (modes.search || 0) + (modes.deep || 0) + (modes.pagination || 0) + (modes.hybrid || 0);
            this.modeChart.data.datasets[0].data = [
                modes.viral || 0,
                modes.ultimate || 0,
                modes.multi || 0,
                modes.infinite || 0,
                other
            ];
            this.modeChart.update('none');
        }

        // Update Velocity Chart
        if (this.velocityChart) {
            const now = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
            const rate = Math.round(this.totals.rate || 0);

            this.velocityData.push({ time: now, rate: rate });
            if (this.velocityData.length > this.maxVelocityPoints) {
                this.velocityData.shift();
            }

            this.velocityChart.data.labels = this.velocityData.map(d => d.time);
            this.velocityChart.data.datasets[0].data = this.velocityData.map(d => d.rate);
            this.velocityChart.update('none');
        }

        // Update Pyramid Chart
        if (this.pyramidChart && this.levelStats) {
            const levels = Object.keys(this.levelStats).sort((a, b) => parseInt(a) - parseInt(b));
            const values = levels.map(l => this.levelStats[l]);
            const totalLevels = document.getElementById('totalLevels');

            if (levels.length > 0) {
                this.pyramidChart.data.labels = levels.map(l => 'Level ' + l);
                this.pyramidChart.data.datasets[0].data = values;
                this.pyramidChart.update('none');
                if (totalLevels) totalLevels.textContent = levels.length + ' levels';
            } else {
                if (totalLevels) totalLevels.textContent = '0 levels';
            }
        }
    },

    /**
     * Update Network Stats
     */
    updateNetworkStats: function() {
        const nodes = this.networkStats.total_nodes || 0;
        const edges = this.networkStats.total_edges || 0;

        document.getElementById('networkNodes').textContent = this.formatNumber(nodes);
        document.getElementById('networkEdges').textContent = this.formatNumber(edges);

        // Calculate network density (simplified)
        const maxEdges = nodes > 1 ? (nodes * (nodes - 1)) / 2 : 0;
        const density = maxEdges > 0 ? ((edges / maxEdges) * 100).toFixed(2) : 0;
        document.getElementById('networkDensity').textContent = density + '%';

        // Average connections per node
        const avgConn = nodes > 0 ? (edges / nodes).toFixed(1) : 0;
        document.getElementById('avgConnections').textContent = avgConn;
    },

    /**
     * Update pool stats in modal
     */
    updatePoolStats: function() {
        document.getElementById('poolPending').textContent = this.formatNumber(this.poolStats.pending || 0);
        document.getElementById('poolClaimed').textContent = this.formatNumber(this.poolStats.claimed || 0);
        document.getElementById('poolDone').textContent = this.formatNumber(this.poolStats.done || 0);
        document.getElementById('poolSeen').textContent = this.formatNumber(this.totals.seen_total || 0);
    },

    // ============================================
    // ACTIONS
    // ============================================

    /**
     * Pause all running processes
     */
    pauseAll: function() {
        if (!confirm('Pause ALL running processes?')) return;
        this.apiCall('dci_pause_all', {}, (result) => {
            console.log('[DCI] Paused', result.affected, 'processes');
        });
    },

    /**
     * Resume all paused processes
     */
    resumeAll: function() {
        this.apiCall('dci_resume_all', {}, (result) => {
            console.log('[DCI] Resumed', result.affected, 'processes');
        });
    },

    /**
     * Stop all processes
     */
    stopAll: function() {
        if (!confirm('STOP ALL processes? This cannot be undone.')) return;
        this.apiCall('dci_stop_all', {}, (result) => {
            console.log('[DCI] Stopped', result.affected, 'processes');
        });
    },

    /**
     * Cleanup dead processes
     */
    cleanupDead: function() {
        this.apiCall('dci_cleanup_dead', {}, (result) => {
            console.log('[DCI] Cleaned up', result.affected, 'dead processes');
        });
    },

    /**
     * Control individual process
     */
    controlProcess: function(processId, action) {
        this.apiCall('dci_control_process', {
            process_id: processId,
            ctrl_action: action
        }, (result) => {
            console.log('[DCI] Process', processId, action);
        });
    },

    /**
     * Show process details modal
     */
    showProcessDetails: function(processId) {
        const modal = document.getElementById('processModal');
        const idEl = document.getElementById('processModalId');
        const bodyEl = document.getElementById('processModalBody');

        idEl.textContent = processId.substring(0, 16) + '...';
        bodyEl.innerHTML = '<div class="loading">Loading process details...</div>';
        modal.classList.add('active');

        this.apiCall('dci_get_process_details', { process_id: processId }, (result) => {
            if (result.error) {
                bodyEl.innerHTML = `<div class="text-danger">${result.error}</div>`;
                return;
            }

            const p = result.process;
            const keywords = JSON.parse(p.keywords || '[]');
            const config = JSON.parse(p.config || '{}');

            bodyEl.innerHTML = `
                <div class="process-details">
                    <div class="process-info-grid">
                        <div class="process-info-item">
                            <div class="process-info-label">Status</div>
                            <div class="process-info-value">
                                <span class="status-badge status-${p.status}">${p.status.toUpperCase()}</span>
                            </div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Mode</div>
                            <div class="process-info-value">
                                <span class="mode-badge mode-${p.mode}">${p.mode}</span>
                            </div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Pool Size</div>
                            <div class="process-info-value">${this.formatNumber(p.pool_size)}</div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Discovered</div>
                            <div class="process-info-value">${this.formatNumber(p.discovered)}</div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Processed</div>
                            <div class="process-info-value">${this.formatNumber(p.processed)}</div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Imported</div>
                            <div class="process-info-value text-success">${this.formatNumber(p.imported)}</div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Duplicates</div>
                            <div class="process-info-value">${this.formatNumber(p.duplicates)}</div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Errors</div>
                            <div class="process-info-value text-danger">${this.formatNumber(p.errors)}</div>
                        </div>
                        <div class="process-info-item">
                            <div class="process-info-label">Skipped</div>
                            <div class="process-info-value">${this.formatNumber(p.skipped)}</div>
                        </div>
                    </div>

                    <div>
                        <h4 style="margin-bottom: 10px; color: #8b949e;">Keywords (${keywords.length})</h4>
                        <div style="background: #0d1117; padding: 10px; border-radius: 6px; max-height: 100px; overflow-y: auto; font-size: 12px;">
                            ${keywords.join(', ')}
                        </div>
                    </div>

                    <div>
                        <h4 style="margin-bottom: 10px; color: #8b949e;">Recent Activity</h4>
                        <div class="process-logs">
                            ${p.logs && p.logs.length > 0 ?
                                p.logs.map(log => `
                                    <div class="process-log-entry">
                                        <span class="text-muted">${new Date(log.created_at).toLocaleTimeString()}</span>
                                        <span class="activity-status ${log.status === 'imported' ? 'imported' : 'error'}">${log.status}</span>
                                        <span style="color: #58a6ff;">${this.truncate(log.url, 80)}</span>
                                    </div>
                                `).join('') :
                                '<div class="text-muted">No activity logs</div>'
                            }
                        </div>
                    </div>
                </div>
            `;
        });
    },

    /**
     * Show config modal
     */
    showConfig: function() {
        document.getElementById('configModal').classList.add('active');
    },

    /**
     * Show pool manager modal
     */
    showPoolManager: function() {
        this.updatePoolStats();
        document.getElementById('poolModal').classList.add('active');
    },

    /**
     * Close modal
     */
    closeModal: function(modalId) {
        document.getElementById(modalId).classList.remove('active');
    },

    /**
     * Load configuration
     */
    loadConfig: function() {
        this.apiCall('dci_get_config', {}, (result) => {
            if (result.config) {
                document.getElementById('cfgConcurrency').value = result.config.default_concurrency || 10;
                document.getElementById('cfgHeartbeat').value = result.config.heartbeat_interval || 15;
                document.getElementById('cfgDeadTimeout').value = result.config.dead_timeout || 45;
                document.getElementById('cfgWaveSize').value = result.config.default_wave_size || 10;
                document.getElementById('cfgAutoCleanup').checked = result.config.auto_cleanup === '1';
            }
        });
    },

    /**
     * Save configuration
     */
    saveConfig: function() {
        const config = {
            default_concurrency: document.getElementById('cfgConcurrency').value,
            heartbeat_interval: document.getElementById('cfgHeartbeat').value,
            dead_timeout: document.getElementById('cfgDeadTimeout').value,
            default_wave_size: document.getElementById('cfgWaveSize').value,
            auto_cleanup: document.getElementById('cfgAutoCleanup').checked ? '1' : '0'
        };

        this.apiCall('dci_save_config', config, (result) => {
            if (result.success) {
                this.closeModal('configModal');
                console.log('[DCI] Configuration saved');
            }
        }, 'POST');
    },

    /**
     * Clear pool URLs
     */
    clearPool: function(status) {
        const msg = status === 'all' ? 'ALL pool URLs' : `${status} pool URLs`;
        if (!confirm(`Clear ${msg}? This cannot be undone.`)) return;

        this.apiCall('dci_clear_pool', { status: status }, (result) => {
            console.log('[DCI] Cleared', result.affected, 'pool URLs');
        });
    },

    /**
     * Clear seen URLs
     */
    clearSeen: function() {
        if (!confirm('Clear ALL seen URLs? This will allow duplicate crawling.')) return;

        this.apiCall('dci_clear_seen', {}, (result) => {
            console.log('[DCI] Cleared seen URLs');
        });
    },

    /**
     * Acknowledge alert
     */
    acknowledgeAlert: function(alertId) {
        this.apiCall('dci_acknowledge_alert', { alert_id: alertId }, (result) => {
            console.log('[DCI] Alert acknowledged');
        });
    },

    /**
     * Toggle auto-scroll
     */
    toggleAutoScroll: function() {
        this.autoScroll = !this.autoScroll;
        const icon = document.getElementById('autoScrollIcon');
        if (icon) {
            icon.textContent = this.autoScroll ? '\u2193' : '\u23F8';
            icon.style.color = this.autoScroll ? '#3fb950' : '#f85149';
        }
    },

    /**
     * Filter processes
     */
    filterProcesses: function() {
        this.modeFilter = document.getElementById('modeFilter').value;
        this.statusFilter = document.getElementById('statusFilter').value;
        this.updateProcessesTable();
    },

    // ============================================
    // UTILITIES
    // ============================================

    /**
     * Make API call
     */
    apiCall: function(action, params, callback, method = 'GET') {
        const url = new URL(window.location.href);
        url.searchParams.set('action', action);

        const options = { method: method };

        if (method === 'POST') {
            options.headers = { 'Content-Type': 'application/json' };
            options.body = JSON.stringify(params);
        } else {
            Object.keys(params).forEach(key => {
                url.searchParams.set(key, params[key]);
            });
        }

        fetch(url.toString(), options)
            .then(response => response.json())
            .then(data => {
                if (callback) callback(data);
            })
            .catch(error => {
                console.error('[DCI] API error:', error);
            });
    },

    /**
     * Format number with commas
     */
    formatNumber: function(num) {
        if (num === null || num === undefined) return '0';
        return parseInt(num).toLocaleString();
    },

    /**
     * Format elapsed time
     */
    formatElapsed: function(seconds) {
        if (!seconds || seconds < 1) return '0s';

        const h = Math.floor(seconds / 3600);
        const m = Math.floor((seconds % 3600) / 60);
        const s = seconds % 60;

        if (h > 0) return `${h}h ${m}m`;
        if (m > 0) return `${m}m ${s}s`;
        return `${s}s`;
    },

    /**
     * Truncate string
     */
    truncate: function(str, len) {
        if (!str) return '';
        if (str.length <= len) return str;
        return str.substring(0, len) + '...';
    }
};

// Export for global access
window.DCI = DCI;
