let networkGraph = null;
let simulation = null;
let showLabels = true;
let pinnedNodes = new Set();
let hiddenCategories = new Set();
let showIsolated = true;

const categoryColors = {
    'core_value': { fill: '#ef4444', stroke: '#fee2e2', gradient: ['#ef4444', '#dc2626'] },
    'hard_constraint': { fill: '#f59e0b', stroke: '#fef3c7', gradient: ['#f59e0b', '#d97706'] },
    'soft_constraint': { fill: '#10b981', stroke: '#d1fae5', gradient: ['#10b981', '#059669'] },
    'factor': { fill: '#3b82f6', stroke: '#dbeafe', gradient: ['#3b82f6', '#2563eb'] }
};

document.addEventListener('DOMContentLoaded', function() {
    const networkTabButton = document.querySelector('[data-tab="network"]');
    
    networkTabButton.addEventListener('click', function() {
        setTimeout(() => {
            initializeNetworkGraph();
        }, 100);
    });
    
    document.getElementById('reset-zoom').addEventListener('click', resetZoom);
    document.getElementById('toggle-labels').addEventListener('click', toggleLabels);
    
    const showIsolatedBtn = document.getElementById('show-isolated');
    if (showIsolatedBtn) {
        showIsolatedBtn.addEventListener('click', toggleIsolated);
    }
    
    document.querySelectorAll('.legend-item').forEach(item => {
        item.addEventListener('click', function() {
            const category = this.dataset.category;
            if (hiddenCategories.has(category)) {
                hiddenCategories.delete(category);
                this.classList.remove('hidden');
            } else {
                hiddenCategories.add(category);
                this.classList.add('hidden');
            }
            
            if (networkGraph) {
                filterByCategory();
            }
        });
    });
});

function initializeNetworkGraph() {
    const container = document.getElementById('network-graph');
    if (!container || !window.appData.graph) {
        return;
    }
    
    container.innerHTML = '';
    
    const width = container.clientWidth;
    const height = container.clientHeight;
    
    const svg = d3.select('#network-graph')
        .append('svg')
        .attr('width', width)
        .attr('height', height)
        .style('background', '#1a1a1a');
    
    const defs = svg.append('defs');
    
    const gradientKeys = Object.keys(categoryColors);
    gradientKeys.forEach(key => {
        const grad = defs.append('radialGradient')
            .attr('id', `grad-${key}`)
            .attr('cx', '50%')
            .attr('cy', '50%')
            .attr('r', '50%')
            .attr('fx', '50%')
            .attr('fy', '50%');
        
        grad.append('stop')
            .attr('offset', '0%')
            .attr('stop-color', categoryColors[key].gradient[0]);
        
        grad.append('stop')
            .attr('offset', '100%')
            .attr('stop-color', categoryColors[key].gradient[1]);
    });
    
    const arrowMarker = defs.append('marker')
        .attr('id', 'arrowhead')
        .attr('viewBox', '-0 -5 10 10')
        .attr('refX', 25)
        .attr('refY', 0)
        .attr('orient', 'auto')
        .attr('markerWidth', 6)
        .attr('markerHeight', 6)
        .append('path')
        .attr('d', 'M 0,-5 L 10 ,0 L 0,5')
        .attr('fill', '#666');
    
    const g = svg.append('g');
    
    const zoom = d3.zoom()
        .scaleExtent([0.1, 4])
        .on('zoom', (event) => {
            g.attr('transform', event.transform);
        });
    
    svg.call(zoom);
    
    const graph = window.appData.graph;
    
    if (!graph.nodes || !graph.edges) {
        container.innerHTML = '<div style="padding: 2rem; text-align: center; color: var(--text-secondary);">No graph data available</div>';
        return;
    }
    
    const nodeConnections = new Map();
    graph.nodes.forEach(n => nodeConnections.set(n.id, new Set()));
    graph.edges.forEach(e => {
        nodeConnections.get(e.source.id || e.source)?.add(e.target.id || e.target);
        nodeConnections.get(e.target.id || e.target)?.add(e.source.id || e.source);
    });
    
    const link = g.append('g')
        .attr('class', 'links')
        .selectAll('line')
        .data(graph.edges)
        .enter()
        .append('line')
        .attr('stroke-width', d => Math.max(1, Math.min(3, Math.sqrt(d.weight))))
        .attr('stroke', '#666')
        .attr('stroke-opacity', 0.6)
        .attr('marker-end', 'url(#arrowhead)');
    
    const node = g.append('g')
        .attr('class', 'nodes')
        .selectAll('g')
        .data(graph.nodes)
        .enter()
        .append('g')
        .call(d3.drag()
            .on('start', dragstarted)
            .on('drag', dragged)
            .on('end', dragended));
    
    const nodeGroups = node.append('circle')
        .attr('r', d => Math.max(5, d.size))
        .attr('fill', d => `url(#grad-${d.category})`)
        .attr('stroke', d => categoryColors[d.category]?.stroke || '#fff')
        .attr('stroke-width', 2)
        .style('filter', 'drop-shadow(0 2px 4px rgba(0,0,0,0.3))')
        .style('cursor', 'grab')
        .on('mouseover', (event, d) => {
            highlightConnections(d, nodeConnections);
            showNodeTooltip(event, d);
        })
        .on('mouseout', () => {
            resetHighlight();
            hideNodeTooltip();
        })
        .on('click', (event, d) => {
            togglePin(d);
            showNodeDetail(event, d);
        })
        .on('dblclick', (event, d) => {
            event.stopPropagation();
            zoomToNode(d);
        });
    
    const pinIcon = node.append('text')
        .attr('text-anchor', 'middle')
        .attr('dy', '0.35em')
        .attr('font-size', '12px')
        .attr('fill', 'white')
        .style('pointer-events', 'none')
        .style('opacity', d => pinnedNodes.has(d.id) ? 1 : 0)
        .text('📌');
    
    const labels = g.append('g')
        .attr('class', 'labels')
        .selectAll('text')
        .data(graph.nodes)
        .enter()
        .append('text')
        .text(d => d.name.replace(/\n/g, ' ').substring(0, 20) + (d.name.length > 20 ? '...' : ''))
        .attr('font-size', '11px')
        .attr('fill', '#e0e0e0')
        .attr('text-anchor', 'middle')
        .attr('dy', d => -Math.max(8, d.size) - 5)
        .style('pointer-events', 'none')
        .style('text-shadow', '0 1px 3px rgba(0,0,0,0.8)')
        .style('opacity', 0.9);
    
    simulation = d3.forceSimulation(graph.nodes)
        .force('link', d3.forceLink(graph.edges).id(d => d.id).distance(80).strength(0.5))
        .force('charge', d3.forceManyBody().strength(-200))
        .force('center', d3.forceCenter(width / 2, height / 2))
        .force('collision', d3.forceCollide().radius(d => Math.max(8, d.size) + 5))
        .force('x', d3.forceX(width / 2).strength(0.05))
        .force('y', d3.forceY(height / 2).strength(0.05))
        .on('tick', ticked);
    
    function ticked() {
        link
            .attr('x1', d => d.source.x)
            .attr('y1', d => d.source.y)
            .attr('x2', d => d.target.x)
            .attr('y2', d => d.target.y);
        
        nodeGroups
            .attr('cx', d => d.x)
            .attr('cy', d => d.y);
        
        node.attr('transform', d => `translate(${d.x},${d.y})`);
        
        labels
            .attr('x', d => d.x)
            .attr('y', d => d.y);
    }
    
    function dragstarted(event, d) {
        if (!event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
        nodeGroups.style('cursor', 'grabbing');
    }
    
    function dragged(event, d) {
        d.fx = event.x;
        d.fy = event.y;
    }
    
    function dragended(event, d) {
        if (!event.active) simulation.alphaTarget(0);
        if (!pinnedNodes.has(d.id)) {
            d.fx = null;
            d.fy = null;
        }
        nodeGroups.style('cursor', 'grab');
    }
    
    function highlightConnections(d, connections) {
        const connectedIds = connections.get(d.id) || new Set();
        connectedIds.add(d.id);
        
        nodeGroups
            .style('opacity', n => connectedIds.has(n.id) ? 1 : 0.1)
            .style('filter', n => {
                if (connectedIds.has(n.id) && n.id !== d.id) {
                    return 'drop-shadow(0 0 8px ' + categoryColors[n.category]?.fill + ')';
                }
                if (n.id === d.id) {
                    return 'drop-shadow(0 0 12px white) drop-shadow(0 4px 8px rgba(0,0,0,0.5))';
                }
                return 'drop-shadow(0 2px 4px rgba(0,0,0,0.3))';
            });
        
        link.style('opacity', l => {
            return (l.source.id === d.id || l.target.id === d.id) ? 1 : 0.1;
        });
        
        labels.style('opacity', n => connectedIds.has(n.id) ? 0.9 : 0.1);
    }
    
    function resetHighlight() {
        nodeGroups
            .style('opacity', 1)
            .style('filter', 'drop-shadow(0 2px 4px rgba(0,0,0,0.3))');
        
        link.style('opacity', 0.6);
        
        labels.style('opacity', showLabels ? 0.9 : 0);
    }
    
    function filterByCategory() {
        const visibleNodes = graph.nodes.filter(n => !hiddenCategories.has(n.category));
        const visibleNodeIds = new Set(visibleNodes.map(n => n.id));
        
        nodeGroups.style('display', n => hiddenCategories.has(n.category) ? 'none' : 'block');
        labels.style('display', n => hiddenCategories.has(n.category) ? 'none' : 'block');
        
        link.style('display', l => {
            const sourceVisible = visibleNodeIds.has(l.source.id);
            const targetVisible = visibleNodeIds.has(l.target.id);
            return sourceVisible && targetVisible ? 'block' : 'none';
        });
        
        if (!showIsolated) {
            const connectedNodeIds = new Set();
            graph.edges.forEach(e => {
                connectedNodeIds.add(e.source.id);
                connectedNodeIds.add(e.target.id);
            });
            
            nodeGroups.style('display', n => {
                if (hiddenCategories.has(n.category)) return 'none';
                if (!showIsolated && !connectedNodeIds.has(n.id)) return 'none';
                return 'block';
            });
            
            labels.style('display', n => {
                if (hiddenCategories.has(n.category)) return 'none';
                if (!showIsolated && !connectedNodeIds.has(n.id)) return 'none';
                return 'block';
            });
        }
        
        simulation.alpha(0.3).restart();
    }
    
    function toggleIsolated() {
        showIsolated = !showIsolated;
        const btn = document.getElementById('show-isolated');
        if (btn) {
            btn.textContent = showIsolated ? 'Hide Isolated' : 'Show Isolated';
        }
        filterByCategory();
    }
    
    function togglePin(d) {
        if (pinnedNodes.has(d.id)) {
            pinnedNodes.delete(d.id);
            pinIcon.style('opacity', 0);
            d.fx = null;
            d.fy = null;
        } else {
            pinnedNodes.add(d.id);
            pinIcon.style('opacity', 1);
            d.fx = d.x;
            d.fy = d.y;
        }
        simulation.alpha(0.3).restart();
    }
    
    function zoomToNode(d) {
        const padding = 100;
        const scale = Math.min(width, height) / (d.size * 10);
        networkGraph.svg.transition()
            .duration(750)
            .call(networkGraph.zoom.transform, 
                d3.zoomIdentity
                    .translate(width / 2, height / 2)
                    .scale(scale)
                    .translate(-d.x, -d.y)
            );
    }
    
    networkGraph = { svg, g, zoom, node, labels, nodeGroups, pinIcon };
}

function showNodeTooltip(event, d) {
    const tooltip = d3.select('body').append('div')
        .attr('class', 'tooltip')
        .style('position', 'absolute')
        .style('background', '#242424')
        .style('color', '#e0e0e0')
        .style('padding', '10px')
        .style('border-radius', '4px')
        .style('pointer-events', 'none')
        .style('z-index', '1000')
        .style('border', '1px solid #444')
        .html(`
            <strong>${d.name}</strong><br/>
            Category: ${d.category}<br/>
            Frequency: ${d.frequency}<br/>
            Coefficient: ${d.coefficient.toFixed(3)}
        `);
    
    tooltip.style('left', (event.pageX + 10) + 'px')
           .style('top', (event.pageY - 10) + 'px');
}

function hideNodeTooltip() {
    d3.selectAll('.tooltip').remove();
}

function showNodeDetail(event, d) {
    const variable = window.appData.variables.find(v => v.name === d.name);
    if (variable) {
        if (typeof showVariableDetail === 'function') {
            showVariableDetail(variable);
        }
    }
}

function resetZoom() {
    if (networkGraph && networkGraph.zoom) {
        networkGraph.svg.transition()
            .duration(750)
            .call(networkGraph.zoom.transform, d3.zoomIdentity);
    }
}

function toggleLabels() {
    showLabels = !showLabels;
    
    if (networkGraph && networkGraph.labels) {
        networkGraph.labels
            .transition()
            .duration(300)
            .style('opacity', showLabels ? 0.9 : 0);
    }
}

function showNodeTooltip(event, d) {
    const connections = Array.from(networkGraph.svg.selectAll('line')
        .filter(l => l.source.id === d.id || l.target.id === d.id)
        .data())
        .map(l => l.source.id === d.id ? l.target.name : l.source.name)
        .slice(0, 5);
    
    const tooltip = d3.select('body').append('div')
        .attr('class', 'tooltip')
        .style('position', 'absolute')
        .style('background', 'rgba(26, 26, 26, 0.95)')
        .style('color', '#e0e0e0')
        .style('padding', '12px')
        .style('border-radius', '8px')
        .style('pointer-events', 'none')
        .style('z-index', '1000')
        .style('border', '1px solid #444')
        .style('box-shadow', '0 4px 12px rgba(0,0,0,0.4)')
        .style('max-width', '250px')
        .html(`
            <div style="font-weight: 600; font-size: 14px; margin-bottom: 8px; color: ${categoryColors[d.category]?.fill || '#fff'}">${d.name}</div>
            <div style="font-size: 12px; color: #999; margin-bottom: 6px;">Category: <span style="color: #e0e0e0">${d.category}</span></div>
            <div style="font-size: 12px; color: #999; margin-bottom: 6px;">Frequency: <span style="color: #e0e0e0">${d.frequency}</span></div>
            <div style="font-size: 12px; color: #999; margin-bottom: 6px;">Coefficient: <span style="color: #e0e0e0">${d.coefficient.toFixed(3)}</span></div>
            ${connections.length > 0 ? `<div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid #444;">
                <div style="font-size: 11px; color: #999; margin-bottom: 4px;">Connected to:</div>
                ${connections.map(c => `<div style="font-size: 11px; color: #ccc;">• ${c.substring(0, 25)}${c.length > 25 ? '...' : ''}</div>`).join('')}
            </div>` : ''}
        `);
    
    const tooltipWidth = 250;
    const tooltipHeight = 150;
    
    let left = event.pageX + 15;
    let top = event.pageY + 15;
    
    if (left + tooltipWidth > window.innerWidth) {
        left = event.pageX - tooltipWidth - 15;
    }
    if (top + tooltipHeight > window.innerHeight) {
        top = event.pageY - tooltipHeight - 15;
    }
    
    tooltip.style('left', left + 'px')
           .style('top', top + 'px');
}

window.addEventListener('resize', function() {
    if (currentTab === 'network') {
        initializeNetworkGraph();
    }
});
