/**
 * 3D Model Architecture Visualization
 * 
 * Interactive 3D visualization of the transformer model architecture,
 * showing layers, attention heads, and data flow with real values.
 * Inspired by neural network architecture diagrams.
 * 
 * @component
 */

"use client";

import { useRef, useState, useEffect, Suspense } from "react";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { getApiUrl } from "@/lib/config";
import { 
  OrbitControls, 
  Text, 
  Box, 
  Plane,
  Line,
  Billboard,
  PerspectiveCamera,
  Environment,
  Float
} from "@react-three/drei";
import * as THREE from "three";
import { 
  Brain,
  Layers,
  Activity,
  Zap,
  Eye,
  GitBranch,
  Maximize2,
  Move3D,
  HelpCircle,
  X,
  Info
} from "lucide-react";

// Layer component representing a transformer layer
function TransformerLayer({ 
  position, 
  layerIndex, 
  attentionValues, 
  onClick,
  isActive 
}: { 
  position: [number, number, number];
  layerIndex: number;
  attentionValues?: number[][];
  onClick?: () => void;
  isActive?: boolean;
}) {
  const meshRef = useRef<THREE.Mesh>(null);
  const [hovered, setHovered] = useState(false);
  
  useFrame((state) => {
    if (meshRef.current) {
      // NO floating animation - layers stay at their exact positions
      // meshRef.current.position.y = position[1]; // Keep at exact position
      
      // Only pulse when active
      if (isActive) {
        const scale = 1 + Math.sin(state.clock.elapsedTime * 3) * 0.05;
        meshRef.current.scale.set(scale, scale, scale);
      }
    }
  });

  return (
    <group position={position}>
      {/* Main layer box */}
      <Box
        ref={meshRef}
        args={[4, 0.3, 3]}
        onClick={onClick}
        onPointerOver={() => setHovered(true)}
        onPointerOut={() => setHovered(false)}
      >
        <meshStandardMaterial
          color={isActive ? "#3b82f6" : hovered ? "#4b5563" : "#1f2937"}
          emissive={isActive ? "#3b82f6" : "#000000"}
          emissiveIntensity={isActive ? 0.2 : 0}
          metalness={0.8}
          roughness={0.2}
          transparent
          opacity={0.9}
        />
      </Box>
      
      {/* Layer label */}
      <Text
        position={[0, 0.3, 0]}
        fontSize={0.15}
        color="white"
        anchorX="center"
        anchorY="middle"
      >
        Layer {layerIndex}
      </Text>
      
      {/* Debug: Show actual position */}
      <Text
        position={[2.5, 0, 0]}
        fontSize={0.08}
        color="#666"
        anchorX="center"
      >
        Y: {position[1].toFixed(1)}
      </Text>
      
      {/* Attention heads visualization */}
      <group position={[0, 0, 1.8]}>
        {Array.from({ length: 16 }).map((_, i) => (
          <Box
            key={i}
            position={[(i % 4 - 1.5) * 0.25, 0, Math.floor(i / 4) * 0.25 - 0.375]}
            args={[0.2, 0.1, 0.2]}
          >
            <meshStandardMaterial
              color={`hsl(${120 + i * 10}, 70%, 50%)`}
              emissive={`hsl(${120 + i * 10}, 70%, 50%)`}
              emissiveIntensity={0.3}
            />
          </Box>
        ))}
        <Text
          position={[0, 0.2, 0]}
          fontSize={0.1}
          color="#9ca3af"
          anchorX="center"
        >
          16 Attention Heads
        </Text>
      </group>
      
      {/* FFN visualization */}
      <group position={[0, 0, -1.8]}>
        <Box args={[3, 0.1, 0.5]}>
          <meshStandardMaterial
            color="#8b5cf6"
            emissive="#8b5cf6"
            emissiveIntensity={0.2}
            metalness={0.6}
            roughness={0.3}
          />
        </Box>
        <Text
          position={[0, 0.15, 0]}
          fontSize={0.1}
          color="#9ca3af"
          anchorX="center"
        >
          FFN (4096d)
        </Text>
      </group>
    </group>
  );
}

// Attention flow visualization
function AttentionFlow({ 
  startPos, 
  endPos,
  intensity = 1,
  color = "#3b82f6"
}: {
  startPos: [number, number, number];
  endPos: [number, number, number];
  intensity?: number;
  color?: string;
}) {
  const lineRef = useRef<THREE.BufferGeometry>(null);
  
  useFrame((state) => {
    // Animate the flow
    const time = state.clock.elapsedTime;
    // You could add particle effects here
  });
  
  const points = [
    new THREE.Vector3(...startPos),
    new THREE.Vector3(...endPos)
  ];
  
  return (
    <Line
      points={points}
      color={color}
      lineWidth={intensity * 2}
      transparent
      opacity={0.6}
    />
  );
}

// Token embedding visualization
function TokenEmbedding({ position }: { position: [number, number, number] }) {
  const meshRef = useRef<THREE.Mesh>(null);
  
  useFrame((state) => {
    if (meshRef.current) {
      meshRef.current.rotation.y = state.clock.elapsedTime * 0.5;
    }
  });
  
  return (
    <group position={position}>
      <Box ref={meshRef} args={[5, 0.2, 2]}>
        <meshStandardMaterial
          color="#10b981"
          emissive="#10b981"
          emissiveIntensity={0.3}
          metalness={0.7}
          roughness={0.2}
        />
      </Box>
      <Text
        position={[0, 0.3, 0]}
        fontSize={0.15}
        color="white"
        anchorX="center"
      >
        Token Embeddings
      </Text>
      <Text
        position={[0, -0.3, 0]}
        fontSize={0.1}
        color="#9ca3af"
        anchorX="center"
      >
        51,200 × 1,024
      </Text>
    </group>
  );
}

// Output layer visualization
function OutputLayer({ position, modelInfo }: { position: [number, number, number]; modelInfo: { layers: number; heads: number; vocabSize: number; hiddenSize: number; totalParams: number } }) {
  const meshRef = useRef<THREE.Mesh>(null);
  const [probabilities, setProbabilities] = useState<number[]>([]);
  
  // Debug log position
  useEffect(() => {
    console.log(`OutputLayer rendered at position: [${position[0]}, ${position[1]}, ${position[2]}]`);
  }, [position]);
  
  useEffect(() => {
    // Simulate probability distribution
    const probs = Array.from({ length: modelInfo.heads }, () => Math.random());
    setProbabilities(probs);
  }, []);
  
  useFrame((state) => {
    if (meshRef.current) {
      meshRef.current.rotation.y = state.clock.elapsedTime * 0.3;
    }
  });
  
  return (
    <group position={position}>
      <Box ref={meshRef} args={[5, 0.2, 2]}>
        <meshStandardMaterial
          color="#f59e0b"
          emissive="#f59e0b"
          emissiveIntensity={0.3}
          metalness={0.7}
          roughness={0.2}
        />
      </Box>
      <Text
        position={[0, 0.3, 0]}
        fontSize={0.15}
        color="white"
        anchorX="center"
      >
        Output Probabilities
      </Text>
      <Text
        position={[0, -0.3, 0]}
        fontSize={0.1}
        color="#9ca3af"
        anchorX="center"
      >
        51,200 tokens
      </Text>
      
      {/* Probability bars */}
      <group position={[0, 0.6, 0]}>
        {probabilities.slice(0, 10).map((prob, i) => (
          <Box
            key={i}
            position={[(i - 4.5) * 0.5, prob * 0.5, 0]}
            args={[0.3, prob, 0.1]}
          >
            <meshStandardMaterial
              color={`hsl(${prob * 120}, 70%, 50%)`}
              emissive={`hsl(${prob * 120}, 70%, 50%)`}
              emissiveIntensity={0.3}
            />
          </Box>
        ))}
      </group>
    </group>
  );
}

// Main 3D scene
function Scene({ modelInfo }: { modelInfo: { layers: number; heads: number; vocabSize: number; hiddenSize: number; totalParams: number } }) {
  const [selectedLayer, setSelectedLayer] = useState<number | null>(null);
  const { camera } = useThree();
  
  // Model configuration from fetched data
  const numLayers = modelInfo.layers;
  const layerSpacing = 3.5; // Much larger spacing for clear separation
  
  // Calculate positions
  const outputYPosition = numLayers * layerSpacing + 5;
  const inputYPosition = -5;
  
  // Log to verify we're creating 20 layers
  useEffect(() => {
    console.log(`Creating ${numLayers} transformer layers`);
    console.log(`Layer spacing: ${layerSpacing}`);
    console.log(`Layer positions: `, Array.from({ length: numLayers }, (_, i) => i * layerSpacing));
    console.log(`Last layer (19) position: ${(numLayers - 1) * layerSpacing}`);
    console.log(`Output position calculated: ${outputYPosition}`);
    console.log(`Input position: ${inputYPosition}`);
  }, []);
  
  return (
    <>
      {/* Lighting */}
      <ambientLight intensity={0.3} />
      <pointLight position={[10, 10, 10]} intensity={1} />
      <pointLight position={[-10, -10, -10]} intensity={0.5} />
      <spotLight position={[0, 20, 0]} angle={0.3} penumbra={1} intensity={1} />
      
      {/* Token Embeddings (Input Layer) */}
      <TokenEmbedding position={[0, inputYPosition, 0]} />
      
      {/* Transformer Layers (0-19) */}
      {Array.from({ length: numLayers }).map((_, i) => {
        const yPosition = i * layerSpacing;
        return (
          <TransformerLayer
            key={`layer-${i}`}
            position={[0, yPosition, 0]}
            layerIndex={i}
            onClick={() => setSelectedLayer(i)}
            isActive={selectedLayer === i}
          />
        );
      })}
      
      {/* Output Layer (After Layer 19) */}
      <OutputLayer position={[0, outputYPosition, 0]} modelInfo={modelInfo} />
      
      {/* Attention flows between layers */}
      {Array.from({ length: numLayers - 1 }).map((_, i) => (
        <AttentionFlow
          key={`flow-${i}`}
          startPos={[0, i * layerSpacing + 0.3, 0]}
          endPos={[0, (i + 1) * layerSpacing - 0.3, 0]}
          intensity={0.5}
        />
      ))}
      
      {/* Flow from input to first layer */}
      <AttentionFlow
        startPos={[0, -4.5, 0]}
        endPos={[0, -0.3, 0]}
        intensity={0.5}
        color="#10b981"
      />
      
      {/* Flow from last layer to output */}
      <AttentionFlow
        startPos={[0, (numLayers - 1) * layerSpacing + 0.3, 0]}
        endPos={[0, outputYPosition - 0.5, 0]}
        intensity={0.5}
        color="#f59e0b"
      />
      
      {/* Grid for reference */}
      <gridHelper args={[150, 150, 0x444444, 0x222222]} />
      
      {/* Layer info display */}
      {selectedLayer !== null && (
        <Billboard position={[5, selectedLayer * layerSpacing, 0]}>
          <Text fontSize={0.2} color="white">
            Layer {selectedLayer} Details
          </Text>
          <Text position={[0, -0.3, 0]} fontSize={0.1} color="#9ca3af">
            • 16 attention heads
          </Text>
          <Text position={[0, -0.5, 0]} fontSize={0.1} color="#9ca3af">
            • 1024 hidden dimensions
          </Text>
          <Text position={[0, -0.7, 0]} fontSize={0.1} color="#9ca3af">
            • 4096 FFN dimensions
          </Text>
          <Text position={[0, -0.9, 0]} fontSize={0.1} color="#9ca3af">
            • Y Position: {(selectedLayer * layerSpacing).toFixed(1)}
          </Text>
        </Billboard>
      )}
      
      {/* Debug: Show output actual position */}
      <Billboard position={[8, outputYPosition, 0]}>
        <Text fontSize={0.15} color="#f59e0b">
          Output Y: {outputYPosition.toFixed(1)}
        </Text>
      </Billboard>
      
      {/* Debug: Show highest layer position */}
      <Billboard position={[-8, (numLayers - 1) * layerSpacing, 0]}>
        <Text fontSize={0.15} color="#3b82f6">
          Layer 19 Y: {((numLayers - 1) * layerSpacing).toFixed(1)}
        </Text>
      </Billboard>
    </>
  );
}

export default function ModelArchitecture3D() {
  const [viewMode, setViewMode] = useState<"perspective" | "top" | "side">("perspective");
  const [showLabels, setShowLabels] = useState(true);
  const [autoRotate, setAutoRotate] = useState(false); // Start without auto-rotate for better control
  const [showExplanation, setShowExplanation] = useState(false);
  
  // Fetch real model data
  const [modelInfo, setModelInfo] = useState({
    layers: 20,
    heads: 16,
    vocabSize: 51200,
    hiddenSize: 1024,
    totalParams: 356712448
  });
  
  useEffect(() => {
    fetch(`${getApiUrl()}/model/info`)
      .then(res => res.json())
      .then(data => {
        setModelInfo({
          layers: data.layers,
          heads: data.heads,
          vocabSize: data.vocabSize,
          hiddenSize: data.hiddenSize,
          totalParams: data.totalParams
        });
      })
      .catch(err => console.log('Using default model info'));
  }, []);
  
  // Generate contextual explanation for current visualization
  const generateExplanation = () => {
    return {
      title: "Transformer Architecture Visualization",
      description: `Interactive 3D view of a ${modelInfo.layers}-layer transformer model with ${modelInfo.heads} attention heads per layer.`,
      details: [
        {
          heading: "What is a Transformer?",
          content: `Transformers are the foundation of modern LLMs. They process text by passing it through multiple layers, each applying attention mechanisms to understand relationships between words. This model has ${modelInfo.layers} layers stacked vertically.`
        },
        {
          heading: "Reading the 3D Structure",
          content: `Bottom (green): Input embeddings convert text to vectors. Middle (blue): ${modelInfo.layers} transformer layers process information. Top (orange): Output layer predicts next tokens. The vertical flow shows how data moves through the network.`
        },
        {
          heading: "Attention Heads (Small Blocks)",
          content: `Each layer contains ${modelInfo.heads} attention heads (colored blocks). These heads learn different aspects of language: grammar, semantics, context, etc. They work in parallel, each focusing on different patterns.`
        },
        {
          heading: "Feed-Forward Networks (Purple)",
          content: `The purple blocks are FFN components with 4096 dimensions. After attention, these networks transform the data further, adding non-linearity and learning complex patterns.`
        },
        {
          heading: "Information Flow",
          content: `Data flows upward from input to output. Each layer refines the understanding, building from simple patterns (early layers) to complex concepts (later layers). The lines show this sequential processing.`
        },
        {
          heading: "Model Scale",
          content: `This architecture represents ~${Math.round(modelInfo.totalParams / 1e6)}M parameters. With ${modelInfo.vocabSize.toLocaleString()} token vocabulary, ${modelInfo.hiddenSize} hidden dimensions, and ${modelInfo.layers} layers, it can generate coherent code by learning patterns from training data.`
        }
      ]
    };
  };
  
  const explanation = generateExplanation();
  
  return (
    <div className="bg-gray-900 rounded-xl p-6 h-[800px]">
      {/* Header */}
      <div className="flex items-center justify-between mb-4">
        <div>
          <h2 className="text-2xl font-bold flex items-center gap-2">
            <Move3D className="w-6 h-6 text-blue-400" />
            3D Model Architecture
          </h2>
          <p className="text-gray-400 mt-1">
            Interactive 3D visualization of the transformer architecture
          </p>
        </div>
        
        {/* Controls */}
        <div className="flex items-center gap-2">
          <button
            onClick={() => setAutoRotate(!autoRotate)}
            className={`px-3 py-1.5 rounded-lg text-sm ${
              autoRotate ? 'bg-blue-600 text-white' : 'bg-gray-800 text-gray-300'
            }`}
          >
            Auto-rotate
          </button>
          <button
            onClick={() => setShowLabels(!showLabels)}
            className={`px-3 py-1.5 rounded-lg text-sm ${
              showLabels ? 'bg-blue-600 text-white' : 'bg-gray-800 text-gray-300'
            }`}
          >
            Labels
          </button>
        </div>
      </div>
      
      {/* Main Content Area with Side Panel */}
      <div className="flex gap-4">
        {/* 3D Canvas */}
        <div className="flex-1 min-w-0 transition-all duration-500 ease-in-out">
          <div className="h-[700px] bg-black rounded-lg relative">
        <Canvas camera={{ position: [50, 40, 70], fov: 45 }}> {/* Camera much further back for full view */}
          <Suspense fallback={null}>
            <Scene modelInfo={modelInfo} />
            <OrbitControls 
              enablePan={true}
              enableZoom={true}
              enableRotate={true}
              autoRotate={autoRotate}
              autoRotateSpeed={0.5}
              minDistance={20}
              maxDistance={200}
              target={[0, 35, 0]}
            />
            <Environment preset="city" />
          </Suspense>
        </Canvas>
        
            {/* Help Toggle Button */}
            <button
              onClick={() => setShowExplanation(!showExplanation)}
              className="absolute top-4 left-4 z-10 p-2 bg-blue-600/90 hover:bg-blue-700 text-white rounded-lg transition-colors flex items-center gap-2 backdrop-blur"
            >
              {showExplanation ? <X className="w-5 h-5" /> : <HelpCircle className="w-5 h-5" />}
              <span className="text-sm font-medium">
                {showExplanation ? 'Hide Info' : 'What am I seeing?'}
              </span>
            </button>
            
            {/* Instructions */}
            <div className="absolute bottom-4 left-4 bg-gray-800/80 backdrop-blur rounded-lg p-3 text-xs text-gray-400">
              <div className="flex items-center gap-2 mb-1">
                <Eye className="w-3 h-3" />
                <span>Click layers to inspect</span>
              </div>
              <div className="flex items-center gap-2 mb-1">
                <Move3D className="w-3 h-3" />
                <span>Drag to rotate • Scroll to zoom</span>
              </div>
              <div className="flex items-center gap-2">
                <Layers className="w-3 h-3" />
                <span>{modelInfo.layers} layers × {modelInfo.heads} heads = {modelInfo.layers * modelInfo.heads} attention patterns</span>
              </div>
              <div className="mt-2 pt-2 border-t border-gray-600">
                <div className="font-semibold text-white">Architecture Stack:</div>
                <div className="text-green-400">↑ Output Probabilities (51,200 tokens)</div>
                <div className="text-blue-400">↑ Layers 0-19 (20 transformer blocks)</div>
                <div className="text-green-400">↑ Input Embeddings (51,200 × 1,024)</div>
              </div>
            </div>
        
        {/* Legend */}
        <div className="absolute top-4 right-4 bg-gray-800/80 backdrop-blur rounded-lg p-3 text-xs">
          <div className="font-semibold text-white mb-2">Components</div>
          <div className="space-y-1">
            <div className="flex items-center gap-2">
              <div className="w-3 h-3 bg-green-500 rounded"></div>
              <span className="text-gray-300">Token Embeddings</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-3 h-3 bg-blue-500 rounded"></div>
              <span className="text-gray-300">Attention Layers</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-3 h-3 bg-purple-500 rounded"></div>
              <span className="text-gray-300">Feed-Forward</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-3 h-3 bg-amber-500 rounded"></div>
              <span className="text-gray-300">Output Layer</span>
            </div>
          </div>
        </div>
          </div>
        </div>
        
        {/* Explanation Side Panel */}
        <div className={`${showExplanation ? 'w-96' : 'w-0'} transition-all duration-500 ease-in-out overflow-hidden`}>
          <div className="w-96 h-[700px] bg-gray-900 rounded-lg border border-gray-700">
            {/* Panel Header */}
            <div className="bg-gray-800 px-4 py-3 border-b border-gray-700">
              <div className="flex items-center gap-2">
                <Info className="w-5 h-5 text-blue-400" />
                <h3 className="text-lg font-semibold text-white">Understanding the Architecture</h3>
              </div>
            </div>
            
            {/* Panel Content */}
            <div className="px-4 py-4 overflow-y-auto h-[calc(700px-60px)]">
              {/* Main Description */}
              <div className="mb-4 p-3 bg-blue-900/20 border border-blue-800 rounded-lg">
                <h4 className="text-sm font-semibold text-blue-400 mb-1">{explanation.title}</h4>
                <p className="text-xs text-gray-300">{explanation.description}</p>
              </div>
              
              {/* Explanation Sections */}
              <div className="space-y-3">
                {explanation.details.map((section, idx) => (
                  <div key={idx} className="bg-gray-800 rounded-lg p-3">
                    <h5 className="font-medium text-sm text-white mb-1 flex items-center gap-1">
                      <Zap className="w-3 h-3 text-yellow-400" />
                      {section.heading}
                    </h5>
                    <p className="text-xs text-gray-300 leading-relaxed">{section.content}</p>
                  </div>
                ))}
              </div>
              
              {/* Visual Guide */}
              <div className="mt-4 p-3 bg-purple-900/20 border border-purple-800 rounded-lg">
                <h4 className="font-medium text-sm text-purple-400 mb-2">Layer Components</h4>
                <div className="space-y-2 text-xs">
                  <div className="flex items-start gap-2">
                    <div className="w-3 h-3 bg-green-500 rounded mt-0.5"></div>
                    <span className="text-gray-300">Input: Token embeddings (51,200 × 1,024)</span>
                  </div>
                  <div className="flex items-start gap-2">
                    <div className="w-3 h-3 bg-blue-500 rounded mt-0.5"></div>
                    <span className="text-gray-300">Attention: {modelInfo.layers} layers × {modelInfo.heads} heads</span>
                  </div>
                  <div className="flex items-start gap-2">
                    <div className="w-3 h-3 bg-purple-500 rounded mt-0.5"></div>
                    <span className="text-gray-300">FFN: 4096 dimensional processing</span>
                  </div>
                  <div className="flex items-start gap-2">
                    <div className="w-3 h-3 bg-amber-500 rounded mt-0.5"></div>
                    <span className="text-gray-300">Output: Probability over 51,200 tokens</span>
                  </div>
                </div>
              </div>
              
              {/* Model Statistics */}
              <div className="mt-4 p-3 bg-gray-800 rounded-lg">
                <h4 className="font-medium text-sm text-gray-300 mb-2">Model Statistics</h4>
                <div className="space-y-1 text-xs">
                  <div className="flex justify-between">
                    <span className="text-gray-400">Total Layers:</span>
                    <span className="text-white">20</span>
                  </div>
                  <div className="flex justify-between">
                    <span className="text-gray-400">Attention Heads:</span>
                    <span className="text-white">16 per layer</span>
                  </div>
                  <div className="flex justify-between">
                    <span className="text-gray-400">Hidden Dimensions:</span>
                    <span className="text-white">1,024</span>
                  </div>
                  <div className="flex justify-between">
                    <span className="text-gray-400">FFN Dimensions:</span>
                    <span className="text-white">4,096</span>
                  </div>
                  <div className="flex justify-between">
                    <span className="text-gray-400">Vocabulary Size:</span>
                    <span className="text-white">51,200 tokens</span>
                  </div>
                  <div className="flex justify-between">
                    <span className="text-gray-400">Parameters:</span>
                    <span className="text-blue-400">~350M</span>
                  </div>
                </div>
              </div>
              
              {/* Interaction Guide */}
              <div className="mt-4 p-3 bg-gray-800 rounded-lg">
                <h4 className="font-medium text-sm text-gray-300 mb-2">💡 Interactive Features</h4>
                <ul className="text-xs text-gray-400 space-y-1">
                  <li>• Click layers to see details</li>
                  <li>• Drag to rotate the model</li>
                  <li>• Scroll to zoom in/out</li>
                  <li>• Enable auto-rotate for 360° view</li>
                  <li>• Each layer processes all tokens in parallel</li>
                </ul>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}