/**
 * Mindmap.js - Interaktive Mind-Map Implementierung
 * - Cytoscape.js für Graph-Rendering
 * - Fetch API für REST-Zugriffe
 * - Socket.IO für Echtzeit-Synchronisation
 */

(async () => {
  /* 1. Initialisierung und Grundkonfiguration */
  const cy = cytoscape({
    container: document.getElementById('cy'),
    style: [
      {
        selector: 'node',
        style: {
          'label': 'data(name)',
          'text-valign': 'center',
          'color': '#fff',
          'background-color': 'data(color)',
          'width': 45,
          'height': 45,
          'font-size': 11,
          'text-outline-width': 1,
          'text-outline-color': '#000',
          'text-outline-opacity': 0.5,
          'text-wrap': 'wrap',
          'text-max-width': 80
        }
      },
      {
        selector: 'node[icon]',
        style: {
          'background-image': function(ele) {
            return `static/img/icons/${ele.data('icon')}.svg`;
          },
          'background-width': '60%',
          'background-height': '60%',
          'background-position-x': '50%',
          'background-position-y': '40%',
          'text-margin-y': 10
        }
      },
      {
        selector: 'edge',
        style: {
          'width': 2,
          'line-color': '#888',
          'target-arrow-shape': 'triangle',
          'curve-style': 'bezier',
          'target-arrow-color': '#888'
        }
      },
      {
        selector: ':selected',
        style: {
          'border-width': 3,
          'border-color': '#f8f32b'
        }
      }
    ],
    layout: { 
      name: 'breadthfirst', 
      directed: true, 
      padding: 30,
      spacingFactor: 1.2
    }
  });

  /* 2. Hilfs-Funktionen für API-Zugriffe */
  const get = async endpoint => {
    try {
      const response = await fetch(endpoint);
      if (!response.ok) {
        console.error(`API-Fehler: ${endpoint} antwortet mit Status ${response.status}`);
        return []; // Leeres Array zurückgeben bei Fehlern
      }
      return await response.json();
    } catch (error) {
      console.error(`Fehler beim Abrufen von ${endpoint}:`, error);
      return []; // Leeres Array zurückgeben bei Netzwerkfehlern
    }
  };
  
  const post = async (endpoint, body) => {
    try {
      const response = await fetch(endpoint, { 
        method: 'POST', 
        headers: { 'Content-Type': 'application/json' }, 
        body: JSON.stringify(body) 
      });
      if (!response.ok) {
        console.error(`API-Fehler: ${endpoint} antwortet mit Status ${response.status}`);
        return {}; // Leeres Objekt zurückgeben bei Fehlern
      }
      return await response.json();
    } catch (error) {
      console.error(`Fehler beim POST zu ${endpoint}:`, error);
      return {}; // Leeres Objekt zurückgeben bei Netzwerkfehlern
    }
  };
  
  const del = async endpoint => {
    try {
      const response = await fetch(endpoint, { method: 'DELETE' });
      if (!response.ok) {
        console.error(`API-Fehler: ${endpoint} antwortet mit Status ${response.status}`);
        return {}; // Leeres Objekt zurückgeben bei Fehlern
      }
      return await response.json();
    } catch (error) {
      console.error(`Fehler beim DELETE zu ${endpoint}:`, error);
      return {}; // Leeres Objekt zurückgeben bei Netzwerkfehlern
    }
  };

  /* 3. Kategorien laden für Style-Informationen */
  let categories = await get('/api/categories');
  
  /* 4. Daten laden und Rendering */
  const loadMindmap = async () => {
    try {
      // Nodes und Beziehungen parallel laden
      const [nodes, relationships] = await Promise.all([
        get('/api/mind_map_nodes'), 
        get('/api/node_relationships')
      ]);
      
      // Graph leeren (für Reload-Fälle)
      cy.elements().remove();
      
      // Überprüfen, ob nodes ein Array ist, wenn nicht, setze es auf ein leeres Array
      const nodesArray = Array.isArray(nodes) ? nodes : [];
      
      // Knoten zum Graph hinzufügen
      cy.add(
        nodesArray.map(node => {
          // Kategorie-Informationen für Styling abrufen
          const category = categories.find(c => c.id === node.category_id) || {};
          
          return {
            data: { 
              id: node.id.toString(),
              name: node.name,
              description: node.description,
              color: node.color_code || category.color_code || '#6b7280',
              icon: node.icon || category.icon,
              category_id: node.category_id
            },
            position: node.x && node.y ? { x: node.x, y: node.y } : undefined
          };
        })
      );
      
      // Überprüfen, ob relationships ein Array ist, wenn nicht, setze es auf ein leeres Array
      const relationshipsArray = Array.isArray(relationships) ? relationships : [];
      
      // Kanten zum Graph hinzufügen
      cy.add(
        relationshipsArray.map(rel => ({
          data: {
            id: `${rel.parent_id}_${rel.child_id}`,
            source: rel.parent_id.toString(),
            target: rel.child_id.toString()
          }
        }))
      );
      
      // Wenn keine Knoten geladen wurden, Fallback-Knoten erstellen
      if (nodesArray.length === 0) {
        // Mindestens einen Standardknoten hinzufügen
        cy.add({
          data: {
            id: 'fallback-1',
            name: 'Mindmap',
            description: 'Erstellen Sie hier Ihre eigene Mindmap',
            color: '#3b82f6',
            icon: 'help-circle'
          },
          position: { x: 300, y: 200 }
        });
        
        // Erfolgsmeldung anzeigen
        console.log('Mindmap erfolgreich initialisiert mit Fallback-Knoten');
        
        // Info-Meldung für Benutzer anzeigen
        const infoBox = document.createElement('div');
        infoBox.classList.add('info-message');
        infoBox.style.position = 'absolute';
        infoBox.style.top = '50%';
        infoBox.style.left = '50%';
        infoBox.style.transform = 'translate(-50%, -50%)';
        infoBox.style.padding = '15px 20px';
        infoBox.style.backgroundColor = 'rgba(59, 130, 246, 0.9)';
        infoBox.style.color = 'white';
        infoBox.style.borderRadius = '8px';
        infoBox.style.zIndex = '5';
        infoBox.style.maxWidth = '80%';
        infoBox.style.textAlign = 'center';
        infoBox.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
        infoBox.innerHTML = 'Mindmap erfolgreich initialisiert.<br>Verwenden Sie die Werkzeugleiste, um Knoten hinzuzufügen.';
        
        document.getElementById('cy').appendChild(infoBox);
        
        // Meldung nach 5 Sekunden ausblenden
        setTimeout(() => {
          infoBox.style.opacity = '0';
          infoBox.style.transition = 'opacity 0.5s ease';
          setTimeout(() => {
            if (infoBox.parentNode) {
              infoBox.parentNode.removeChild(infoBox);
            }
          }, 500);
        }, 5000);
      }
      
      // Layout anwenden wenn keine Positionsdaten vorhanden
      const nodesWithoutPosition = cy.nodes().filter(node => 
        !node.position() || (node.position().x === 0 && node.position().y === 0)
      );
      
      if (nodesWithoutPosition.length > 0) {
        cy.layout({ 
          name: 'breadthfirst', 
          directed: true, 
          padding: 30,
          spacingFactor: 1.2
        }).run();
      }
      
      // Tooltip-Funktionalität
      cy.nodes().unbind('mouseover').bind('mouseover', (event) => {
        const node = event.target;
        const description = node.data('description');
        
        if (description) {
          const tooltip = document.getElementById('node-tooltip') || 
                          document.createElement('div');
          
          if (!tooltip.id) {
            tooltip.id = 'node-tooltip';
            tooltip.style.position = 'absolute';
            tooltip.style.backgroundColor = '#333';
            tooltip.style.color = '#fff';
            tooltip.style.padding = '8px';
            tooltip.style.borderRadius = '4px';
            tooltip.style.maxWidth = '250px';
            tooltip.style.zIndex = 10;
            tooltip.style.pointerEvents = 'none';
            tooltip.style.transition = 'opacity 0.2s';
            tooltip.style.boxShadow = '0 2px 10px rgba(0,0,0,0.3)';
            document.body.appendChild(tooltip);
          }
          
          const renderedPosition = node.renderedPosition();
          const containerRect = cy.container().getBoundingClientRect();
          
          tooltip.innerHTML = description;
          tooltip.style.left = (containerRect.left + renderedPosition.x + 25) + 'px';
          tooltip.style.top = (containerRect.top + renderedPosition.y - 15) + 'px';
          tooltip.style.opacity = '1';
        }
      });
      
      cy.nodes().unbind('mouseout').bind('mouseout', () => {
        const tooltip = document.getElementById('node-tooltip');
        if (tooltip) {
          tooltip.style.opacity = '0';
        }
      });
      
    } catch (error) {
      console.error('Fehler beim Laden der Mindmap:', error);
      alert('Die Mindmap konnte nicht geladen werden. Bitte prüfen Sie die Konsole für Details.');
    }
  };
  
  // Initial laden
  await loadMindmap();

  /* 5. Socket.IO für Echtzeit-Synchronisation */
  const socket = io();
  
  socket.on('node_added', async (node) => {
    // Kategorie-Informationen für Styling abrufen
    const category = categories.find(c => c.id === node.category_id) || {};
    
    cy.add({
      data: { 
        id: node.id.toString(),
        name: node.name,
        description: node.description,
        color: node.color_code || category.color_code || '#6b7280',
        icon: node.icon || category.icon,
        category_id: node.category_id
      }
    });
    
    // Layout neu anwenden, wenn nötig
    if (!node.x || !node.y) {
      cy.layout({ name: 'breadthfirst', directed: true, padding: 30 }).run();
    }
  });
  
  socket.on('node_updated', (node) => {
    const cyNode = cy.$id(node.id.toString());
    if (cyNode.length > 0) {
      // Kategorie-Informationen für Styling abrufen
      const category = categories.find(c => c.id === node.category_id) || {};
      
      cyNode.data({
        name: node.name,
        description: node.description,
        color: node.color_code || category.color_code || '#6b7280',
        icon: node.icon || category.icon,
        category_id: node.category_id
      });
      
      if (node.x && node.y) {
        cyNode.position({ x: node.x, y: node.y });
      }
    }
  });
  
  socket.on('node_deleted', (nodeId) => {
    const cyNode = cy.$id(nodeId.toString());
    if (cyNode.length > 0) {
      cy.remove(cyNode);
    }
  });
  
  socket.on('relationship_added', (rel) => {
    cy.add({
      data: {
        id: `${rel.parent_id}_${rel.child_id}`,
        source: rel.parent_id.toString(),
        target: rel.child_id.toString()
      }
    });
  });
  
  socket.on('relationship_deleted', (rel) => {
    const edgeId = `${rel.parent_id}_${rel.child_id}`;
    const cyEdge = cy.$id(edgeId);
    if (cyEdge.length > 0) {
      cy.remove(cyEdge);
    }
  });
  
  socket.on('category_updated', async () => {
    // Kategorien neu laden
    categories = await get('/api/categories');
    // Nodes aktualisieren, die diese Kategorie verwenden
    cy.nodes().forEach(node => {
      const categoryId = node.data('category_id');
      if (categoryId) {
        const category = categories.find(c => c.id === categoryId);
        if (category) {
          node.data('color', node.data('color_code') || category.color_code);
          node.data('icon', node.data('icon') || category.icon);
        }
      }
    });
  });

  /* 6. UI-Interaktionen */
  // Knoten hinzufügen
  const btnAddNode = document.getElementById('addNode');
  if (btnAddNode) {
    btnAddNode.addEventListener('click', async () => {
      const name = prompt('Knotenname eingeben:');
      if (!name) return;
      
      const description = prompt('Beschreibung (optional):');
      
      // Kategorie auswählen
      let categoryId = null;
      if (categories.length > 0) {
        const categoryOptions = categories.map((c, i) => `${i}: ${c.name}`).join('\n');
        const categoryChoice = prompt(
          `Kategorie auswählen (Nummer eingeben):\n${categoryOptions}`,
          '0'
        );
        
        if (categoryChoice !== null) {
          const index = parseInt(categoryChoice, 10);
          if (!isNaN(index) && index >= 0 && index < categories.length) {
            categoryId = categories[index].id;
          }
        }
      }
      
      // Knoten erstellen
      await post('/api/mind_map_node', { 
        name, 
        description,
        category_id: categoryId
      });
      // Darstellung wird durch Socket.IO Event übernommen
    });
  }
  
  // Verbindung hinzufügen
  const btnAddEdge = document.getElementById('addEdge');
  if (btnAddEdge) {
    btnAddEdge.addEventListener('click', async () => {
      const sel = cy.$('node:selected');
      if (sel.length !== 2) {
        alert('Bitte genau zwei Knoten auswählen (Parent → Child)');
        return;
      }
      
      const [parent, child] = sel.map(node => node.id());
      await post('/api/node_relationship', { 
        parent_id: parent, 
        child_id: child 
      });
      // Darstellung wird durch Socket.IO Event übernommen
    });
  }
  
  // Knoten bearbeiten
  const btnEditNode = document.getElementById('editNode');
  if (btnEditNode) {
    btnEditNode.addEventListener('click', async () => {
      const sel = cy.$('node:selected');
      if (sel.length !== 1) {
        alert('Bitte genau einen Knoten auswählen');
        return;
      }
      
      const node = sel[0];
      const nodeData = node.data();
      
      const name = prompt('Knotenname:', nodeData.name);
      if (!name) return;
      
      const description = prompt('Beschreibung:', nodeData.description || '');
      
      // Kategorie auswählen
      let categoryId = nodeData.category_id;
      if (categories.length > 0) {
        const categoryOptions = categories.map((c, i) => `${i}: ${c.name}`).join('\n');
        const categoryChoice = prompt(
          `Kategorie auswählen (Nummer eingeben):\n${categoryOptions}`,
          categories.findIndex(c => c.id === categoryId).toString()
        );
        
        if (categoryChoice !== null) {
          const index = parseInt(categoryChoice, 10);
          if (!isNaN(index) && index >= 0 && index < categories.length) {
            categoryId = categories[index].id;
          }
        }
      }
      
      // Knoten aktualisieren
      await post(`/api/mind_map_node/${nodeData.id}`, { 
        name, 
        description,
        category_id: categoryId
      });
      // Darstellung wird durch Socket.IO Event übernommen
    });
  }
  
  // Knoten löschen
  const btnDeleteNode = document.getElementById('deleteNode');
  if (btnDeleteNode) {
    btnDeleteNode.addEventListener('click', async () => {
      const sel = cy.$('node:selected');
      if (sel.length !== 1) {
        alert('Bitte genau einen Knoten auswählen');
        return;
      }
      
      if (confirm('Sind Sie sicher, dass Sie diesen Knoten löschen möchten?')) {
        const nodeId = sel[0].id();
        await del(`/api/mind_map_node/${nodeId}`);
        // Darstellung wird durch Socket.IO Event übernommen
      }
    });
  }
  
  // Verbindung löschen
  const btnDeleteEdge = document.getElementById('deleteEdge');
  if (btnDeleteEdge) {
    btnDeleteEdge.addEventListener('click', async () => {
      const sel = cy.$('edge:selected');
      if (sel.length !== 1) {
        alert('Bitte genau eine Verbindung auswählen');
        return;
      }
      
      if (confirm('Sind Sie sicher, dass Sie diese Verbindung löschen möchten?')) {
        const edge = sel[0];
        const parentId = edge.source().id();
        const childId = edge.target().id();
        
        await del(`/api/node_relationship/${parentId}/${childId}`);
        // Darstellung wird durch Socket.IO Event übernommen
      }
    });
  }
  
  // Layout aktualisieren
  const btnReLayout = document.getElementById('reLayout');
  if (btnReLayout) {
    btnReLayout.addEventListener('click', () => {
      cy.layout({ 
        name: 'breadthfirst', 
        directed: true, 
        padding: 30,
        spacingFactor: 1.2
      }).run();
    });
  }

  /* 7. Position speichern bei Drag & Drop */
  cy.on('dragfree', 'node', async (e) => {
    const node = e.target;
    const position = node.position();
    
    await post(`/api/mind_map_node/${node.id()}/position`, {
      x: Math.round(position.x),
      y: Math.round(position.y)
    });
    
    // Andere Benutzer erhalten die Position über den node_updated Event
  });

  /* 8. Kontextmenü (optional) */
  const setupContextMenu = () => {
    cy.on('cxttap', 'node', function(e) {
      const node = e.target;
      const nodeData = node.data();
      
      // Position des Kontextmenüs berechnen
      const renderedPosition = node.renderedPosition();
      const containerRect = cy.container().getBoundingClientRect();
      const menuX = containerRect.left + renderedPosition.x;
      const menuY = containerRect.top + renderedPosition.y;
      
      // Kontextmenü erstellen oder aktualisieren
      let contextMenu = document.getElementById('context-menu');
      if (!contextMenu) {
        contextMenu = document.createElement('div');
        contextMenu.id = 'context-menu';
        contextMenu.style.position = 'absolute';
        contextMenu.style.backgroundColor = '#fff';
        contextMenu.style.border = '1px solid #ccc';
        contextMenu.style.borderRadius = '4px';
        contextMenu.style.padding = '5px 0';
        contextMenu.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';
        contextMenu.style.zIndex = 1000;
        document.body.appendChild(contextMenu);
      }
      
      // Menüinhalte
      contextMenu.innerHTML = `
        <div class="menu-item" data-action="edit">Knoten bearbeiten</div>
        <div class="menu-item" data-action="connect">Verbindung erstellen</div>
        <div class="menu-item" data-action="delete">Knoten löschen</div>
      `;
      
      // Styling für Menüpunkte
      const menuItems = contextMenu.querySelectorAll('.menu-item');
      menuItems.forEach(item => {
        item.style.padding = '8px 20px';
        item.style.cursor = 'pointer';
        item.style.fontSize = '14px';
        
        item.addEventListener('mouseover', function() {
          this.style.backgroundColor = '#f0f0f0';
        });
        
        item.addEventListener('mouseout', function() {
          this.style.backgroundColor = 'transparent';
        });
        
        // Event-Handler
        item.addEventListener('click', async function() {
          const action = this.getAttribute('data-action');
          
          switch(action) {
            case 'edit':
              // Knoten bearbeiten (gleiche Logik wie beim Edit-Button)
              const name = prompt('Knotenname:', nodeData.name);
              if (name) {
                const description = prompt('Beschreibung:', nodeData.description || '');
                await post(`/api/mind_map_node/${nodeData.id}`, { name, description });
              }
              break;
              
            case 'connect':
              // Modus zum Verbinden aktivieren
              cy.nodes().unselect();
              node.select();
              alert('Wählen Sie nun einen zweiten Knoten aus, um eine Verbindung zu erstellen');
              break;
              
            case 'delete':
              if (confirm('Sind Sie sicher, dass Sie diesen Knoten löschen möchten?')) {
                await del(`/api/mind_map_node/${nodeData.id}`);
              }
              break;
          }
          
          // Menü schließen
          contextMenu.style.display = 'none';
        });
      });
      
      // Menü positionieren und anzeigen
      contextMenu.style.left = menuX + 'px';
      contextMenu.style.top = menuY + 'px';
      contextMenu.style.display = 'block';
      
      // Event-Listener zum Schließen des Menüs
      const closeMenu = function() {
        if (contextMenu) {
          contextMenu.style.display = 'none';
        }
        document.removeEventListener('click', closeMenu);
      };
      
      // Verzögerung, um den aktuellen Click nicht zu erfassen
      setTimeout(() => {
        document.addEventListener('click', closeMenu);
      }, 0);
      
      e.preventDefault();
    });
  };
  
  // Kontextmenü aktivieren (optional)
  // setupContextMenu();

  /* 9. Export-Funktion (optional) */
  const btnExport = document.getElementById('exportMindmap');
  if (btnExport) {
    btnExport.addEventListener('click', () => {
      const elements = cy.json().elements;
      const exportData = {
        nodes: elements.nodes.map(n => ({
          id: n.data.id,
          name: n.data.name,
          description: n.data.description,
          category_id: n.data.category_id,
          x: Math.round(n.position?.x || 0),
          y: Math.round(n.position?.y || 0)
        })),
        relationships: elements.edges.map(e => ({
          parent_id: e.data.source,
          child_id: e.data.target
        }))
      };
      
      const blob = new Blob([JSON.stringify(exportData, null, 2)], {type: 'application/json'});
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = 'mindmap_export.json';
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    });
  }

  /* 10. Filter-Funktion nach Kategorien (optional) */
  const setupCategoryFilters = () => {
    const filterContainer = document.getElementById('category-filters');
    if (!filterContainer || !categories.length) return;
    
    filterContainer.innerHTML = '';
    
    // "Alle anzeigen" Option
    const allBtn = document.createElement('button');
    allBtn.innerText = 'Alle Kategorien';
    allBtn.className = 'category-filter active';
    allBtn.onclick = () => {
      document.querySelectorAll('.category-filter').forEach(btn => btn.classList.remove('active'));
      allBtn.classList.add('active');
      cy.nodes().removeClass('filtered').show();
      cy.edges().show();
    };
    filterContainer.appendChild(allBtn);
    
    // Filter-Button pro Kategorie
    categories.forEach(category => {
      const btn = document.createElement('button');
      btn.innerText = category.name;
      btn.className = 'category-filter';
      btn.style.backgroundColor = category.color_code;
      btn.style.color = '#fff';
      btn.onclick = () => {
        document.querySelectorAll('.category-filter').forEach(btn => btn.classList.remove('active'));
        btn.classList.add('active');
        
        const matchingNodes = cy.nodes().filter(node => node.data('category_id') === category.id);
        cy.nodes().addClass('filtered').hide();
        matchingNodes.removeClass('filtered').show();
        
        // Verbindungen zu/von diesen Knoten anzeigen
        cy.edges().hide();
        matchingNodes.connectedEdges().show();
      };
      filterContainer.appendChild(btn);
    });
  };
  
  // Filter-Funktionalität aktivieren (optional)
  // setupCategoryFilters();

  /* 11. Suchfunktion (optional) */
  const searchInput = document.getElementById('search-mindmap');
  if (searchInput) {
    searchInput.addEventListener('input', (e) => {
      const searchTerm = e.target.value.toLowerCase();
      
      if (!searchTerm) {
        cy.nodes().removeClass('search-hidden').show();
        cy.edges().show();
        return;
      }
      
      cy.nodes().forEach(node => {
        const name = node.data('name').toLowerCase();
        const description = (node.data('description') || '').toLowerCase();
        
        if (name.includes(searchTerm) || description.includes(searchTerm)) {
          node.removeClass('search-hidden').show();
          node.connectedEdges().show();
        } else {
          node.addClass('search-hidden').hide();
          // Kanten nur verstecken, wenn beide verbundenen Knoten versteckt sind
          node.connectedEdges().forEach(edge => {
            const otherNode = edge.source().id() === node.id() ? edge.target() : edge.source();
            if (otherNode.hasClass('search-hidden')) {
              edge.hide();
            }
          });
        }
      });
    });
  }

  console.log('Mindmap erfolgreich initialisiert');
})(); 