{% extends "base.html" %}

{% block title %}Graf Relacji Encji - ZOPK Baza Wiedzy{% endblock %}

{% block extra_css %}
<style>
    .page-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: var(--spacing-lg);
    }

    .page-header h1 {
        font-size: var(--font-size-2xl);
        color: var(--text-primary);
    }

    .breadcrumb {
        display: flex;
        gap: var(--spacing-xs);
        color: var(--text-secondary);
        font-size: var(--font-size-sm);
        margin-bottom: var(--spacing-lg);
    }

    .breadcrumb a {
        color: var(--primary);
        text-decoration: none;
    }

    .breadcrumb a:hover {
        text-decoration: underline;
    }

    .graph-container {
        position: relative;
        background: var(--surface);
        border-radius: var(--radius-lg);
        box-shadow: var(--shadow);
        overflow: hidden;
    }

    .graph-controls {
        position: absolute;
        top: var(--spacing-md);
        left: var(--spacing-md);
        z-index: 10;
        display: flex;
        flex-direction: column;
        gap: var(--spacing-sm);
    }

    .control-group {
        background: rgba(255,255,255,0.95);
        padding: var(--spacing-sm) var(--spacing-md);
        border-radius: var(--radius);
        box-shadow: var(--shadow);
    }

    .control-group label {
        display: block;
        font-size: var(--font-size-xs);
        color: var(--text-secondary);
        margin-bottom: 4px;
    }

    .control-group select,
    .control-group input {
        padding: 4px 8px;
        border: 1px solid var(--border);
        border-radius: var(--radius-sm);
        font-size: var(--font-size-sm);
    }

    .graph-stats {
        position: absolute;
        top: var(--spacing-md);
        right: var(--spacing-md);
        z-index: 10;
        background: rgba(255,255,255,0.95);
        padding: var(--spacing-sm) var(--spacing-md);
        border-radius: var(--radius);
        box-shadow: var(--shadow);
        font-size: var(--font-size-sm);
    }

    .graph-stats strong {
        color: var(--primary);
    }

    #graph-svg {
        width: 100%;
        height: 700px;
        cursor: grab;
    }

    #graph-svg:active {
        cursor: grabbing;
    }

    .node {
        cursor: pointer;
    }

    .node circle {
        stroke: #fff;
        stroke-width: 2px;
        transition: all 0.2s ease;
    }

    .node:hover circle {
        stroke-width: 4px;
        filter: brightness(1.1);
    }

    .node text {
        font-size: 10px;
        fill: var(--text-primary);
        pointer-events: none;
        text-anchor: middle;
        dominant-baseline: middle;
    }

    .link {
        stroke: #999;
        stroke-opacity: 0.4;
    }

    .link:hover {
        stroke-opacity: 0.8;
    }

    /* Node colors by type */
    .node-company { fill: #3b82f6; }
    .node-person { fill: #ec4899; }
    .node-place { fill: #10b981; }
    .node-organization { fill: #f59e0b; }
    .node-project { fill: #8b5cf6; }
    .node-event { fill: #ef4444; }
    .node-other { fill: #6b7280; }

    /* Tooltip */
    .tooltip {
        position: absolute;
        background: rgba(0,0,0,0.8);
        color: white;
        padding: 8px 12px;
        border-radius: var(--radius);
        font-size: var(--font-size-sm);
        pointer-events: none;
        z-index: 100;
        max-width: 250px;
    }

    .tooltip h4 {
        margin: 0 0 4px 0;
        font-size: var(--font-size-base);
    }

    .tooltip p {
        margin: 0;
        font-size: var(--font-size-xs);
        opacity: 0.8;
    }

    /* Legend */
    .legend {
        position: absolute;
        bottom: var(--spacing-md);
        left: var(--spacing-md);
        background: rgba(255,255,255,0.95);
        padding: var(--spacing-sm) var(--spacing-md);
        border-radius: var(--radius);
        box-shadow: var(--shadow);
        display: flex;
        flex-wrap: wrap;
        gap: var(--spacing-md);
        font-size: var(--font-size-xs);
    }

    .legend-item {
        display: flex;
        align-items: center;
        gap: 4px;
    }

    .legend-dot {
        width: 12px;
        height: 12px;
        border-radius: 50%;
    }

    .loading-overlay {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(255,255,255,0.9);
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 20;
    }

    .loading-spinner {
        width: 48px;
        height: 48px;
        border: 4px solid var(--border);
        border-top-color: var(--primary);
        border-radius: 50%;
        animation: spin 1s linear infinite;
    }

    @keyframes spin {
        to { transform: rotate(360deg); }
    }

    .btn {
        display: inline-flex;
        align-items: center;
        gap: var(--spacing-xs);
        padding: 6px 12px;
        border-radius: var(--radius);
        font-size: var(--font-size-sm);
        font-weight: 500;
        cursor: pointer;
        transition: var(--transition);
        text-decoration: none;
        border: none;
        background: var(--primary);
        color: white;
    }

    .btn:hover {
        background: var(--primary-dark);
    }
</style>
{% endblock %}

{% block content %}
<div class="container">
    <div class="breadcrumb">
        <a href="{{ url_for('admin_zopk') }}">Panel ZOPK</a>
        <span>›</span>
        <a href="{{ url_for('admin_zopk_knowledge_dashboard') }}">Baza Wiedzy</a>
        <span>›</span>
        <span>Graf Relacji</span>
    </div>

    <div class="page-header">
        <h1>🕸️ Graf Współwystępowania Encji</h1>
    </div>

    <div class="graph-container">
        <div class="loading-overlay" id="loadingOverlay">
            <div class="loading-spinner"></div>
        </div>

        <div class="graph-controls">
            <div class="control-group">
                <label>Typ encji:</label>
                <select id="entityType" onchange="loadGraph()">
                    <option value="">Wszystkie</option>
                    <option value="company">Firmy</option>
                    <option value="person">Osoby</option>
                    <option value="place">Miejsca</option>
                    <option value="organization">Organizacje</option>
                    <option value="project">Projekty</option>
                </select>
            </div>
            <div class="control-group">
                <label>Min. współwystąpień:</label>
                <input type="range" id="minCooccurrence" min="2" max="10" value="3"
                       oninput="document.getElementById('cooccurValue').textContent = this.value"
                       onchange="loadGraph()">
                <span id="cooccurValue">3</span>
            </div>
            <div class="control-group">
                <button class="btn" onclick="resetZoom()">🔄 Reset widoku</button>
            </div>
        </div>

        <div class="graph-stats" id="graphStats">
            Ładowanie...
        </div>

        <svg id="graph-svg"></svg>

        <div class="legend">
            <div class="legend-item">
                <div class="legend-dot node-company"></div>
                <span>Firmy</span>
            </div>
            <div class="legend-item">
                <div class="legend-dot node-person"></div>
                <span>Osoby</span>
            </div>
            <div class="legend-item">
                <div class="legend-dot node-place"></div>
                <span>Miejsca</span>
            </div>
            <div class="legend-item">
                <div class="legend-dot node-organization"></div>
                <span>Organizacje</span>
            </div>
            <div class="legend-item">
                <div class="legend-dot node-project"></div>
                <span>Projekty</span>
            </div>
        </div>
    </div>
</div>

<!-- Tooltip -->
<div class="tooltip" id="tooltip" style="display: none;"></div>
{% endblock %}

{% block extra_js %}
// D3 is loaded by base.html AFTER this block, so we need to wait
// Use window.onload to ensure D3 script from base.html is fully loaded
window.addEventListener('load', function() {
    if (typeof d3 !== 'undefined') {
        initGraph();
    } else {
        console.error('D3.js not loaded!');
    }
});

let simulation, svg, g, link, node, zoom;
let currentNodes = [];
let currentLinks = [];

function initGraph() {
    svg = d3.select('#graph-svg');
    const width = svg.node().getBoundingClientRect().width;
    const height = 700;

    // Create zoom behavior
    zoom = d3.zoom()
        .scaleExtent([0.1, 4])
        .on('zoom', (event) => {
            g.attr('transform', event.transform);
        });

    svg.call(zoom);

    // Create container group
    g = svg.append('g');

    // Create link and node groups
    g.append('g').attr('class', 'links');
    g.append('g').attr('class', 'nodes');

    loadGraph();
}

async function loadGraph() {
    const overlay = document.getElementById('loadingOverlay');
    overlay.style.display = 'flex';

    const entityType = document.getElementById('entityType').value;
    const minCooccurrence = document.getElementById('minCooccurrence').value;

    try {
        const url = `/api/zopk/knowledge/graph/data?entity_type=${entityType}&min_cooccurrence=${minCooccurrence}&limit=200`;
        const response = await fetch(url);
        const data = await response.json();

        if (data.success) {
            currentNodes = data.nodes;
            currentLinks = data.links;
            updateGraph();
            document.getElementById('graphStats').innerHTML =
                `<strong>${data.stats.total_nodes}</strong> encji • <strong>${data.stats.total_links}</strong> połączeń`;
        } else {
            console.error('Error loading graph:', data.error);
        }
    } catch (error) {
        console.error('Error:', error);
    } finally {
        overlay.style.display = 'none';
    }
}

function updateGraph() {
    const width = svg.node().getBoundingClientRect().width;
    const height = 700;

    // Stop existing simulation
    if (simulation) simulation.stop();

    // Clear existing elements
    g.select('.links').selectAll('*').remove();
    g.select('.nodes').selectAll('*').remove();

    // Create links
    link = g.select('.links')
        .selectAll('line')
        .data(currentLinks)
        .enter()
        .append('line')
        .attr('class', 'link')
        .attr('stroke-width', d => Math.sqrt(d.value));

    // Create nodes
    node = g.select('.nodes')
        .selectAll('g')
        .data(currentNodes)
        .enter()
        .append('g')
        .attr('class', 'node')
        .call(d3.drag()
            .on('start', dragstarted)
            .on('drag', dragged)
            .on('end', dragended))
        .on('mouseover', showTooltip)
        .on('mouseout', hideTooltip);

    // Add circles
    node.append('circle')
        .attr('r', d => Math.max(8, Math.min(30, Math.sqrt(d.mentions) * 2)))
        .attr('class', d => `node-${getNodeType(d.type)}`);

    // Add labels for larger nodes
    node.filter(d => d.mentions >= 10)
        .append('text')
        .attr('dy', d => Math.max(8, Math.min(30, Math.sqrt(d.mentions) * 2)) + 12)
        .text(d => d.name.length > 15 ? d.name.slice(0, 15) + '...' : d.name);

    // Create simulation
    simulation = d3.forceSimulation(currentNodes)
        .force('link', d3.forceLink(currentLinks)
            .id(d => d.id)
            .distance(100)
            .strength(d => Math.min(1, d.value / 10)))
        .force('charge', d3.forceManyBody().strength(-200))
        .force('center', d3.forceCenter(width / 2, height / 2))
        .force('collision', d3.forceCollide().radius(d => Math.max(8, Math.sqrt(d.mentions) * 2) + 5))
        .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);

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

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;
}

function showTooltip(event, d) {
    const tooltip = document.getElementById('tooltip');
    tooltip.innerHTML = `
        <h4>${d.name}</h4>
        <p>Typ: ${d.type}</p>
        <p>Wzmianki: ${d.mentions}</p>
        ${d.verified ? '<p>✅ Zweryfikowano</p>' : ''}
    `;
    tooltip.style.display = 'block';
    tooltip.style.left = (event.pageX + 10) + 'px';
    tooltip.style.top = (event.pageY + 10) + 'px';
}

function hideTooltip() {
    document.getElementById('tooltip').style.display = 'none';
}

function getNodeType(type) {
    const typeMap = {
        'company': 'company',
        'person': 'person',
        'place': 'place',
        'Lokalizacja': 'place',
        'organization': 'organization',
        'Organizacja': 'organization',
        'project': 'project',
        'Projekt': 'project',
        'event': 'event'
    };
    return typeMap[type] || 'other';
}

function resetZoom() {
    svg.transition().duration(500).call(
        zoom.transform,
        d3.zoomIdentity
    );
}
{% endblock %}
