import React, { useState, useEffect, useRef } from 'react';
import { FileText, Zap, Network } from 'lucide-react';

interface KnowledgeGraphVisualizerProps {
  jsonText: string;
}


const KnowledgeGraphVisualizer: React.FC<KnowledgeGraphVisualizerProps> = ({jsonText}) => {
  const [inputText, setInputText] = useState('');
  const [entities, setEntities] = useState([]);
  const [relationships, setRelationships] = useState([]);
  const [selectedEntity, setSelectedEntity] = useState(null);
  const canvasRef = useRef(null);
  const [nodes, setNodes] = useState([]);
  const [isDragging, setIsDragging] = useState(false);
  const [draggedNode, setDraggedNode] = useState(null);

  const sampleText = jsonText;

  const extractEntities = (text) => {
    const entityPatterns = {
      person: /\b([A-Z][a-z]+ [A-Z][a-z]+)\b/g,
      organization: /\b(Google|Facebook|Stanford University|MIT)\b/g,
      concept: /\b(Artificial Intelligence|Machine Learning|Deep Learning|AI|neural networks|TensorFlow|PyTorch)\b/g,
      award: /\b(Turing Award)\b/g
    };

    const extractedEntities = new Map();

    Object.entries(entityPatterns).forEach(([type, pattern]) => {
      const matches = [...text.matchAll(pattern)];
      matches.forEach(match => {
        const entity = match[1] || match[0];
        if (!extractedEntities.has(entity)) {
          extractedEntities.set(entity, { 
            name: entity, 
            type, 
            mentions: 1,
            contexts: [text.substring(Math.max(0, match.index - 50), Math.min(text.length, match.index + 50))]
          });
        } else {
          extractedEntities.get(entity).mentions++;
        }
      });
    });

    return Array.from(extractedEntities.values());
  };

  const extractRelationships = (text, entities) => {
    const rels = [];
    const entityNames = entities.map(e => e.name);
    
    const sentences = text.split(/[.!?]+/);
    
    sentences.forEach(sentence => {
      const foundEntities = entityNames.filter(name => 
        sentence.includes(name)
      );

      if (foundEntities.length >= 2) {
        for (let i = 0; i < foundEntities.length - 1; i++) {
          for (let j = i + 1; j < foundEntities.length; j++) {
            const relationship = inferRelationship(sentence, foundEntities[i], foundEntities[j]);
            rels.push({
              source: foundEntities[i],
              target: foundEntities[j],
              type: relationship,
              context: sentence.trim()
            });
          }
        }
      }
    });

    return rels;
  };

  const inferRelationship = (sentence, entity1, entity2) => {
    const lowerSentence = sentence.toLowerCase();
    
    if (lowerSentence.includes('developed') || lowerSentence.includes('created')) {
      return 'created';
    } else if (lowerSentence.includes('subset') || lowerSentence.includes('part of')) {
      return 'subset_of';
    } else if (lowerSentence.includes('won') || lowerSentence.includes('received')) {
      return 'received';
    } else if (lowerSentence.includes('work on') || lowerSentence.includes('research')) {
      return 'researched';
    } else if (lowerSentence.includes('uses') || lowerSentence.includes('enables')) {
      return 'uses';
    } else {
      return 'related_to';
    }
  };

  const analyzeDocument = () => {
    const text = inputText || sampleText;
    const extractedEntities = extractEntities(text);
    const extractedRelationships = extractRelationships(text, extractedEntities);
    
    setEntities(extractedEntities);
    setRelationships(extractedRelationships);
    
    initializeGraph(extractedEntities, extractedRelationships);
  };

  const initializeGraph = (entityList, relationshipList) => {
    const width = 800;
    const height = 600;
    const centerX = width / 2;
    const centerY = height / 2;
    
    const nodeMap = new Map();
    
    entityList.forEach((entity, index) => {
      const angle = (index / entityList.length) * 2 * Math.PI;
      const radius = Math.min(width, height) * 0.35;
      
      nodeMap.set(entity.name, {
        ...entity,
        x: centerX + radius * Math.cos(angle),
        y: centerY + radius * Math.sin(angle),
        vx: 0,
        vy: 0
      });
    });

    setNodes(Array.from(nodeMap.values()));
  };

  useEffect(() => {
    if (nodes.length > 0) {
      const canvas = canvasRef.current;
      if (!canvas) return;
      
      const ctx = canvas.getContext('2d');
      const width = canvas.width;
      const height = canvas.height;

      const animate = () => {
        ctx.clearRect(0, 0, width, height);

        // Draw relationships
        ctx.strokeStyle = '#94a3b8';
        ctx.lineWidth = 1.5;
        relationships.forEach(rel => {
          const source = nodes.find(n => n.name === rel.source);
          const target = nodes.find(n => n.name === rel.target);
          
          if (source && target) {
            ctx.beginPath();
            ctx.moveTo(source.x, source.y);
            ctx.lineTo(target.x, target.y);
            ctx.stroke();
          }
        });

        // Draw nodes
        nodes.forEach(node => {
          const isSelected = selectedEntity === node.name;
          const radius = 8 + (node.mentions * 2);
          
          const colors = {
            person: '#3b82f6',
            organization: '#10b981',
            concept: '#f59e0b',
            award: '#ec4899'
          };

          ctx.beginPath();
          ctx.arc(node.x, node.y, radius, 0, 2 * Math.PI);
          ctx.fillStyle = isSelected ? '#ef4444' : colors[node.type] || '#6366f1';
          ctx.fill();
          ctx.strokeStyle = '#ffffff';
          ctx.lineWidth = 2;
          ctx.stroke();

          // Draw labels
          ctx.fillStyle = '#1e293b';
          ctx.font = isSelected ? 'bold 13px system-ui' : '12px system-ui';
          ctx.textAlign = 'center';
          ctx.fillText(node.name, node.x, node.y - radius - 8);
        });
      };

      // Simple physics simulation
      const physics = () => {
        const updatedNodes = nodes.map(node => {
          let fx = 0, fy = 0;

          // Repulsion from other nodes
          nodes.forEach(other => {
            if (other.name !== node.name) {
              const dx = node.x - other.x;
              const dy = node.y - other.y;
              const dist = Math.sqrt(dx * dx + dy * dy) || 1;
              const force = 2000 / (dist * dist);
              fx += (dx / dist) * force;
              fy += (dy / dist) * force;
            }
          });

          // Attraction along edges
          relationships.forEach(rel => {
            if (rel.source === node.name) {
              const target = nodes.find(n => n.name === rel.target);
              if (target) {
                const dx = target.x - node.x;
                const dy = target.y - node.y;
                const dist = Math.sqrt(dx * dx + dy * dy) || 1;
                fx += dx * 0.01;
                fy += dy * 0.01;
              }
            }
            if (rel.target === node.name) {
              const source = nodes.find(n => n.name === rel.source);
              if (source) {
                const dx = source.x - node.x;
                const dy = source.y - node.y;
                fx += dx * 0.01;
                fy += dy * 0.01;
              }
            }
          });

          // Center gravity
          fx += (width / 2 - node.x) * 0.01;
          fy += (height / 2 - node.y) * 0.01;

          // Apply forces with damping
          const newVx = (node.vx + fx) * 0.85;
          const newVy = (node.vy + fy) * 0.85;

          return {
            ...node,
            vx: newVx,
            vy: newVy,
            x: Math.max(30, Math.min(width - 30, node.x + newVx)),
            y: Math.max(30, Math.min(height - 30, node.y + newVy))
          };
        });

        setNodes(updatedNodes);
      };

      const interval = setInterval(() => {
        if (!isDragging) {
          physics();
        }
        animate();
      }, 50);

      return () => clearInterval(interval);
    }
  }, [nodes, relationships, selectedEntity, isDragging]);

  const handleCanvasClick = (e) => {
    const canvas = canvasRef.current;
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    const clicked = nodes.find(node => {
      const dx = x - node.x;
      const dy = y - node.y;
      const radius = 8 + (node.mentions * 2);
      return Math.sqrt(dx * dx + dy * dy) <= radius;
    });

    setSelectedEntity(clicked ? clicked.name : null);
  };

  const handleMouseDown = (e) => {
    const canvas = canvasRef.current;
    const rect = canvas.getBoundingClientRect();
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;

    const node = nodes.find(n => {
      const dx = x - n.x;
      const dy = y - n.y;
      const radius = 8 + (n.mentions * 2);
      return Math.sqrt(dx * dx + dy * dy) <= radius;
    });

    if (node) {
      setIsDragging(true);
      setDraggedNode(node.name);
    }
  };

  const handleMouseMove = (e) => {
    if (isDragging && draggedNode) {
      const canvas = canvasRef.current;
      const rect = canvas.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const y = e.clientY - rect.top;

      setNodes(prev => prev.map(n => 
        n.name === draggedNode ? { ...n, x, y, vx: 0, vy: 0 } : n
      ));
    }
  };

  const handleMouseUp = () => {
    setIsDragging(false);
    setDraggedNode(null);
  };

  const selectedEntityData = selectedEntity ? entities.find(e => e.name === selectedEntity) : null;
  const selectedRelationships = selectedEntity 
    ? relationships.filter(r => r.source === selectedEntity || r.target === selectedEntity)
    : [];

  return (
    <div className="min-h-screen bg-gradient-to-br from-slate-50 to-blue-50">
      <div className="max-w-7xl mx-auto">

        <div className="w-full h-full gap-6">
          <div className="lg:col-span-2">
            

            <div className="bg-white rounded-lg shadow-lg p-6">
              <canvas
                ref={canvasRef}
                width={800}
                height={600}
                className="w-full border border-slate-200 rounded-lg cursor-pointer bg-slate-50"
                onClick={handleCanvasClick}
                onMouseDown={handleMouseDown}
                onMouseMove={handleMouseMove}
                onMouseUp={handleMouseUp}
                onMouseLeave={handleMouseUp}
              />
            </div>
          </div>

          <div className="bg-white rounded-lg shadow-lg p-6 mb-2">
              <div className="flex items-center gap-2 mb-4">
                <FileText className="w-5 h-5 text-slate-600" />
                <h2 className="text-xl font-semibold text-slate-900">Document Input</h2>
              </div>
              <textarea
                className="w-full h-32 p-4 border border-slate-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none"
                placeholder="Paste your document here or use the sample text..."
                value={inputText}
                onChange={(e) => setInputText(e.target.value)}
              />
              <button
                onClick={analyzeDocument}
                className="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg flex items-center justify-center gap-2 transition-colors"
              >
                <Zap className="w-5 h-5" />
                Analyze Document
              </button>
            </div>

          {/* <div className="space-y-6">
            <div className="bg-white rounded-lg shadow-lg p-6">
              <h2 className="text-xl font-semibold text-slate-900 mb-4">
                {selectedEntityData ? 'Entity Details' : 'Entities'}
              </h2>
              
              {selectedEntityData ? (
                <div>
                  <div className="mb-4 pb-4 border-b border-slate-200">
                    <h3 className="font-bold text-lg text-slate-900">{selectedEntityData.name}</h3>
                    <p className="text-sm text-slate-600 capitalize mt-1">{selectedEntityData.type}</p>
                    <p className="text-sm text-slate-500 mt-1">Mentions: {selectedEntityData.mentions}</p>
                  </div>
                  
                  <div className="mb-4">
                    <h4 className="font-semibold text-slate-900 mb-2">Relationships</h4>
                    <div className="space-y-2">
                      {selectedRelationships.map((rel, idx) => (
                        <div key={idx} className="text-sm bg-slate-50 p-2 rounded">
                          <span className="font-medium text-slate-900">
                            {rel.source === selectedEntity ? rel.target : rel.source}
                          </span>
                          <span className="text-slate-500 mx-2">•</span>
                          <span className="text-slate-600 capitalize">{rel.type.replace('_', ' ')}</span>
                        </div>
                      ))}
                    </div>
                  </div>

                  <button
                    onClick={() => setSelectedEntity(null)}
                    className="text-sm text-blue-600 hover:text-blue-700"
                  >
                    ← Back to all entities
                  </button>
                </div>
              ) : (
                <div className="space-y-2 max-h-96 overflow-y-auto">
                  {entities.map((entity, idx) => (
                    <div
                      key={idx}
                      onClick={() => setSelectedEntity(entity.name)}
                      className="p-3 bg-slate-50 hover:bg-slate-100 rounded-lg cursor-pointer transition-colors"
                    >
                      <div className="flex items-center justify-between">
                        <span className="font-medium text-slate-900">{entity.name}</span>
                        <span className="text-xs text-slate-500">{entity.mentions}</span>
                      </div>
                      <span className="text-xs text-slate-600 capitalize">{entity.type}</span>
                    </div>
                  ))}
                </div>
              )}
            </div>

            
          </div> */}
        </div>
      </div>
    </div>
  );
};

export default KnowledgeGraphVisualizer;