{% extends "base.html" %}

{% set active_tab = "graph" %}

{% block title %}Knowledge Graph - Second Brain{% endblock %}

{% block content_class %}browsing{% endblock %}

{% block content %}
<div class="graph-container" id="graphContainer">
    <div class="graph-header">
        <h2>Knowledge Graph</h2>
        <div class="graph-controls">
            <button id="resetView" class="btn btn-view">Reset View</button>
        </div>
    </div>
    <div class="graph-legend">
        <div class="legend-item">
            <span class="legend-node"></span>
            <span>Page</span>
        </div>
        <div class="legend-item">
            <span class="legend-edge"></span>
            <span>Link</span>
        </div>
        <div class="legend-item legend-hint">
            Scroll to zoom · Drag nodes to arrange · Click nodes to focus
        </div>
    </div>
    <div id="graphSvg" class="graph-svg"></div>
    <div class="graph-tooltip" id="tooltip"></div>
</div>

<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script>
const tooltip = document.getElementById('tooltip');

// Load graph data
fetch('/api/graph')
    .then(r => r.json())
    .then(data => {
        const width = document.getElementById('graphContainer').clientWidth;
        const height = Math.max(window.innerHeight - 200, 500);

        const svg = d3.select('#graphSvg')
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .attr('viewBox', [0, 0, width, height]);

        // Zoom behavior
        const g = svg.append('g');
        const zoom = d3.zoom()
            .scaleExtent([0.3, 4])
            .on('zoom', (event) => {
                g.attr('transform', event.transform);
            });
        svg.call(zoom);

        // Prepare nodes and links
        const nodes = data.nodes.map(d => ({...d}));
        const links = data.edges.map(d => ({...d}));

        // Create force simulation
        const simulation = d3.forceSimulation(nodes)
            .force('link', d3.forceLink(links).id(d => d.id).distance(150))
            .force('charge', d3.forceManyBody().strength(-400))
            .force('center', d3.forceCenter(width / 2, height / 2))
            .force('collision', d3.forceCollide().radius(30));

        // Draw links
        const link = g.append('g')
            .selectAll('line')
            .data(links)
            .join('line')
            .attr('class', 'graph-link')
            .attr('stroke', 'var(--border)')
            .attr('stroke-width', 1.5);

        // Draw nodes
        const node = g.append('g')
            .selectAll('g')
            .data(nodes)
            .join('g')
            .attr('class', 'graph-node')
            .call(d3.drag()
                .on('start', dragstarted)
                .on('drag', dragged)
                .on('end', dragended));

        // Node circles
        node.append('circle')
            .attr('class', 'graph-node-circle')
            .attr('r', 8)
            .attr('fill', d => getNodeColor(d))
            .attr('stroke', 'var(--bg-secondary)')
            .attr('stroke-width', 2);

        // Node labels
        node.append('text')
            .attr('class', 'graph-node-label')
            .attr('dx', 14)
            .attr('dy', 4)
            .text(d => d.title)
            .style('fill', 'var(--text-primary)')
            .style('font-size', '11px')
            .style('pointer-events', 'none');

        // Node interactions
        node.on('mouseover', function(event, d) {
            d3.select(this).select('circle')
                .transition().duration(200)
                .attr('r', 12)
                .attr('stroke', 'var(--accent)');

            // Show tooltip
            tooltip.innerHTML = `
                <strong>${d.title}</strong>
                ${d.tags.length ? `<br>Tags: ${d.tags.join(', ')}` : ''}
                <br><small>${(d.size / 1024).toFixed(1)} KB</small>
            `;
            tooltip.style.opacity = 1;
        })
        .on('mousemove', function(event) {
            tooltip.style.left = (event.pageX + 15) + 'px';
            tooltip.style.top = (event.pageY - 10) + 'px';
        })
        .on('mouseout', function() {
            d3.select(this).select('circle')
                .transition().duration(200)
                .attr('r', 8)
                .attr('stroke', 'var(--bg-secondary)');
            tooltip.style.opacity = 0;
        })
        .on('click', function(event, d) {
            window.location.href = `/wiki/${d.id}`;
        });

        // Link interactions
        link.on('mouseover', function(event, d) {
            d3.select(this).attr('stroke', 'var(--accent)').attr('stroke-width', 2.5);
        })
        .on('mouseout', function() {
            d3.select(this).attr('stroke', 'var(--border)').attr('stroke-width', 1.5);
        });

        // Simulation tick
        simulation.on('tick', () => {
            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);

            node.attr('transform', d => `translate(${d.x},${d.y})`);
        });

        // Reset view button
        document.getElementById('resetView').addEventListener('click', () => {
            svg.transition().duration(750).call(
                zoom.transform,
                d3.zoomIdentity
            );
        });

        // Drag functions
        function dragstarted(event, d) {
            if (!event.active) simulation.alphaTarget(0.3).restart();
            d.fx = d.x;
            d.fy = d.y;
        }

        function dragged(event, d) {
            d.fx = event.x;
            d.fy = event.y;
        }

        function dragended(event, d) {
            if (!event.active) simulation.alphaTarget(0);
            d.fx = null;
            d.fy = null;
        }

        // Color function based on tags
        function getNodeColor(d) {
            const colorMap = {
                'project': '#3b82f6',
                'daily': '#22c55e',
                'system': '#f59e0b',
                'reference': '#8b5cf6',
                'default': '#6b7280',
            };
            for (const tag of d.tags) {
                const lower = tag.toLowerCase();
                if (lower in colorMap) return colorMap[lower];
            }
            return colorMap['default'];
        }
    })
    .catch(err => {
        document.getElementById('graphSvg').innerHTML = `
            <div class="error-state">
                <p>Failed to load graph data: ${err.message}</p>
            </div>
        `;
    });
</script>
{% endblock %}