{% extends "base.html" %}

{% block title %}Mapa Powiazań - Norda Biznes Partner{% endblock %}

{% block extra_css %}
<style>
    .connections-container {
        width: 100%;
        height: calc(100vh - 200px);
        min-height: 600px;
        background: #1a1a2e;
        border-radius: 12px;
        position: relative;
        overflow: hidden;
    }

    #connections-graph {
        width: 100%;
        height: 100%;
    }

    .node-company {
        cursor: pointer;
    }

    .node-person {
        cursor: pointer;
    }

    .link {
        stroke: #4a90d9;
        stroke-opacity: 0.4;
    }

    .link.zarzad {
        stroke: #e74c3c;
    }

    .link.wspolnik {
        stroke: #2ecc71;
    }

    .link.prokurent {
        stroke: #f39c12;
    }

    .link.wlasciciel_jdg {
        stroke: #9b59b6;
    }

    .node-label {
        font-size: 10px;
        fill: #fff;
        pointer-events: none;
        text-shadow: 0 1px 2px rgba(0,0,0,0.8);
    }

    .tooltip {
        position: absolute;
        padding: 12px 16px;
        background: rgba(26, 26, 46, 0.95);
        border: 1px solid #4a90d9;
        border-radius: 8px;
        color: #fff;
        font-size: 13px;
        pointer-events: none;
        z-index: 1000;
        max-width: 300px;
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    }

    .tooltip h4 {
        margin: 0 0 8px 0;
        color: #4a90d9;
        font-size: 14px;
    }

    .tooltip p {
        margin: 4px 0;
    }

    .tooltip .role-badge {
        display: inline-block;
        padding: 2px 6px;
        border-radius: 4px;
        font-size: 11px;
        margin: 2px;
    }

    .tooltip .role-badge.zarzad {
        background: #e74c3c;
    }

    .tooltip .role-badge.wspolnik {
        background: #2ecc71;
    }

    .tooltip .role-badge.prokurent {
        background: #f39c12;
    }

    .tooltip .role-badge.wlasciciel_jdg {
        background: #9b59b6;
    }

    .controls {
        position: absolute;
        top: 16px;
        right: 16px;
        display: flex;
        flex-direction: column;
        gap: 8px;
        z-index: 100;
    }

    .control-btn {
        padding: 8px 16px;
        background: rgba(74, 144, 217, 0.9);
        border: none;
        border-radius: 6px;
        color: #fff;
        cursor: pointer;
        font-size: 13px;
        transition: background 0.2s;
    }

    .control-btn:hover {
        background: rgba(74, 144, 217, 1);
    }

    .legend {
        position: absolute;
        bottom: 16px;
        left: 16px;
        background: rgba(26, 26, 46, 0.9);
        padding: 12px 16px;
        border-radius: 8px;
        z-index: 100;
    }

    .legend h4 {
        margin: 0 0 8px 0;
        color: #fff;
        font-size: 13px;
    }

    .legend-item {
        display: flex;
        align-items: center;
        gap: 8px;
        margin: 4px 0;
        font-size: 12px;
        color: #ccc;
    }

    .legend-color {
        width: 16px;
        height: 16px;
        border-radius: 50%;
    }

    .legend-line {
        width: 24px;
        height: 3px;
        border-radius: 2px;
    }

    .stats-panel {
        position: absolute;
        top: 16px;
        left: 16px;
        background: rgba(26, 26, 46, 0.9);
        padding: 12px 16px;
        border-radius: 8px;
        z-index: 100;
    }

    .stats-panel h4 {
        margin: 0 0 8px 0;
        color: #4a90d9;
        font-size: 14px;
    }

    .stats-panel .stat {
        display: flex;
        justify-content: space-between;
        gap: 16px;
        margin: 4px 0;
        font-size: 13px;
        color: #ccc;
    }

    .stats-panel .stat-value {
        color: #fff;
        font-weight: 600;
    }

    .page-header {
        margin-bottom: 20px;
    }

    .page-header h1 {
        font-size: 28px;
        margin: 0;
    }

    .page-header p {
        color: #888;
        margin: 8px 0 0 0;
    }

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

    .loading-text {
        color: #fff;
        font-size: 16px;
    }

    .source-info {
        margin-top: 16px;
        font-size: 12px;
        color: #666;
    }

    .source-info a {
        color: #4a90d9;
    }
</style>
{% endblock %}

{% block content %}
<div class="page-header">
    <h1>Mapa Powiazań Norda Biznes</h1>
    <p>Wizualizacja powiązań między firmami członkowskimi a osobami (zarząd, wspólnicy, prokurenci)</p>
</div>

<div class="connections-container" id="container">
    <div class="loading-overlay" id="loading">
        <div class="loading-text">Ładowanie danych...</div>
    </div>

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

    <div class="stats-panel" id="stats">
        <h4>Statystyki</h4>
        <div class="stat">
            <span>Firmy:</span>
            <span class="stat-value" id="stat-companies">-</span>
        </div>
        <div class="stat">
            <span>Osoby:</span>
            <span class="stat-value" id="stat-people">-</span>
        </div>
        <div class="stat">
            <span>Powiązania:</span>
            <span class="stat-value" id="stat-connections">-</span>
        </div>
    </div>

    <div class="controls">
        <button class="control-btn" onclick="fitToScreen()" style="background: rgba(34, 197, 94, 0.9);">Dopasuj widok</button>
        <button class="control-btn" onclick="resetZoom()">Reset widoku</button>
        <button class="control-btn" onclick="toggleLabels()">Pokaż/ukryj etykiety</button>
    </div>

    <div class="legend">
        <h4>Legenda</h4>
        <div class="legend-item">
            <div class="legend-color" style="background: #4a90d9;"></div>
            <span>Firma</span>
        </div>
        <div class="legend-item">
            <div class="legend-color" style="background: #f39c12;"></div>
            <span>Osoba</span>
        </div>
        <div class="legend-item">
            <div class="legend-line" style="background: #e74c3c;"></div>
            <span>Zarząd</span>
        </div>
        <div class="legend-item">
            <div class="legend-line" style="background: #2ecc71;"></div>
            <span>Wspólnik</span>
        </div>
        <div class="legend-item">
            <div class="legend-line" style="background: #f39c12;"></div>
            <span>Prokurent</span>
        </div>
        <div class="legend-item">
            <div class="legend-line" style="background: #9b59b6;"></div>
            <span>Właściciel JDG</span>
        </div>
    </div>

    <div class="tooltip" id="tooltip" style="display: none;"></div>
</div>

<div class="source-info">
    Źródło danych: <a href="https://ekrs.ms.gov.pl" target="_blank">ekrs.ms.gov.pl</a> (KRS),
    <a href="https://dane.biznes.gov.pl" target="_blank">dane.biznes.gov.pl</a> (CEIDG)
</div>

<script src="{{ url_for('static', filename='js/vendor/d3.v7.min.js') }}"></script>
<script>
// D3.js Force-Directed Graph for Company-Person Connections
let simulation, svg, g, zoom, showLabels = true;
let graphData = { nodes: [], links: [] };

// Wait for D3 to be available
function waitForD3(callback) {
    if (typeof d3 !== 'undefined') {
        callback();
    } else {
        setTimeout(() => waitForD3(callback), 100);
    }
}

async function loadData() {
    try {
        const response = await fetch('/api/connections');
        const data = await response.json();

        if (!data.success) {
            throw new Error('Failed to load data');
        }

        graphData = data;

        // Update stats
        document.getElementById('stat-companies').textContent = data.stats.companies;
        document.getElementById('stat-people').textContent = data.stats.people;
        document.getElementById('stat-connections').textContent = data.stats.connections;

        // Hide loading
        document.getElementById('loading').style.display = 'none';

        // Initialize graph
        initGraph(data.nodes, data.links);

    } catch (error) {
        console.error('Error loading data:', error);
        document.querySelector('#loading .loading-text').textContent = 'Błąd ładowania danych';
    }
}

function initGraph(nodes, links) {
    const container = document.getElementById('container');
    const width = container.clientWidth;
    const height = container.clientHeight;

    svg = d3.select('#connections-graph')
        .attr('width', width)
        .attr('height', height);

    // Clear previous content
    svg.selectAll('*').remove();

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

    svg.call(zoom);

    // Create container for graph elements
    g = svg.append('g');

    // Create simulation - optimized for large graph
    simulation = d3.forceSimulation(nodes)
        .force('link', d3.forceLink(links).id(d => d.id).distance(80).strength(0.5))
        .force('charge', d3.forceManyBody().strength(-150).distanceMax(300))
        .force('center', d3.forceCenter(width / 2, height / 2))
        .force('collision', d3.forceCollide().radius(20))
        .force('x', d3.forceX(width / 2).strength(0.05))
        .force('y', d3.forceY(height / 2).strength(0.05));

    // Auto-fit after initial layout (2 seconds)
    setTimeout(() => {
        fitToScreen();
    }, 2000);

    // Create links
    const link = g.append('g')
        .selectAll('line')
        .data(links)
        .join('line')
        .attr('class', d => `link ${d.category}`)
        .attr('stroke-width', 2);

    // Create nodes
    const node = g.append('g')
        .selectAll('g')
        .data(nodes)
        .join('g')
        .attr('class', d => d.type === 'company' ? 'node-company' : 'node-person')
        .call(drag(simulation));

    // Add circles to nodes
    node.append('circle')
        .attr('r', d => {
            if (d.type === 'company') return 12;
            return 6 + (d.company_count || 1) * 2;
        })
        .attr('fill', d => d.type === 'company' ? '#4a90d9' : '#f39c12')
        .attr('stroke', '#fff')
        .attr('stroke-width', 1.5);

    // Add labels
    node.append('text')
        .attr('class', 'node-label')
        .attr('dx', 15)
        .attr('dy', 4)
        .text(d => {
            if (d.type === 'company') return d.name.length > 20 ? d.name.substring(0, 20) + '...' : d.name;
            return d.name;
        });

    // Add tooltip interaction
    const tooltip = d3.select('#tooltip');

    node.on('mouseover', (event, d) => {
        let html = `<h4>${d.name}</h4>`;

        if (d.type === 'company') {
            html += `<p>Kategoria: ${d.category}</p>`;
            if (d.city) html += `<p>Miasto: ${d.city}</p>`;

            // Find connected people
            const connected = links.filter(l => l.target.id === d.id || l.source.id === d.id);
            if (connected.length > 0) {
                html += `<p>Powiązania:</p>`;
                connected.forEach(l => {
                    const person = l.source.id === d.id ? l.target : l.source;
                    if (person.type === 'person') {
                        html += `<span class="role-badge ${l.category}">${l.role}</span> ${person.name}<br>`;
                    }
                });
            }
        } else {
            html += `<p>Powiązany z ${d.company_count} firmami</p>`;

            // Find connected companies
            const connected = links.filter(l => l.source.id === d.id || l.target.id === d.id);
            if (connected.length > 0) {
                connected.forEach(l => {
                    const company = l.source.id === d.id ? l.target : l.source;
                    if (company.type === 'company') {
                        html += `<span class="role-badge ${l.category}">${l.role}</span> ${company.name}<br>`;
                    }
                });
            }
        }

        tooltip.html(html)
            .style('display', 'block')
            .style('left', (event.pageX + 15) + 'px')
            .style('top', (event.pageY - 10) + 'px');
    })
    .on('mousemove', (event) => {
        tooltip
            .style('left', (event.pageX + 15) + 'px')
            .style('top', (event.pageY - 10) + 'px');
    })
    .on('mouseout', () => {
        tooltip.style('display', 'none');
    })
    .on('click', (event, d) => {
        if (d.type === 'company' && d.slug) {
            window.location.href = `/company/${d.slug}`;
        }
    });

    // Update positions on 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})`);
    });
}

function drag(simulation) {
    function dragstarted(event) {
        if (!event.active) simulation.alphaTarget(0.3).restart();
        event.subject.fx = event.subject.x;
        event.subject.fy = event.subject.y;
    }

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

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

    return d3.drag()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended);
}

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

function fitToScreen() {
    if (!graphData.nodes || graphData.nodes.length === 0) return;

    const container = document.getElementById('container');
    const width = container.clientWidth;
    const height = container.clientHeight;

    // Calculate bounding box of all nodes
    let minX = Infinity, maxX = -Infinity;
    let minY = Infinity, maxY = -Infinity;

    graphData.nodes.forEach(n => {
        if (n.x !== undefined && n.y !== undefined) {
            minX = Math.min(minX, n.x);
            maxX = Math.max(maxX, n.x);
            minY = Math.min(minY, n.y);
            maxY = Math.max(maxY, n.y);
        }
    });

    if (minX === Infinity) return;

    // Add padding
    const padding = 50;
    minX -= padding;
    maxX += padding;
    minY -= padding;
    maxY += padding;

    // Calculate scale and translation
    const graphWidth = maxX - minX;
    const graphHeight = maxY - minY;
    const scale = Math.min(width / graphWidth, height / graphHeight, 1.5);
    const centerX = (minX + maxX) / 2;
    const centerY = (minY + maxY) / 2;

    // Apply transform
    svg.transition()
        .duration(750)
        .call(zoom.transform, d3.zoomIdentity
            .translate(width / 2, height / 2)
            .scale(scale)
            .translate(-centerX, -centerY));
}

function toggleLabels() {
    showLabels = !showLabels;
    d3.selectAll('.node-label').style('display', showLabels ? 'block' : 'none');
}

// Handle window resize
window.addEventListener('resize', () => {
    if (graphData.nodes.length > 0) {
        initGraph(graphData.nodes, graphData.links);
    }
});

// Load data on page load - wait for D3 first
document.addEventListener('DOMContentLoaded', () => {
    waitForD3(loadData);
});
</script>
{% endblock %}
