"use client";

import { useMemo, useRef, useState } from "react";
import { Canvas, useFrame, useThree } from "@react-three/fiber";
import { MeshDistortMaterial, Sphere, Preload, Float } from "@react-three/drei";
import * as THREE from "three";

// --- CONFIGURATION ---
const NEURON_COUNT = 18; // Fewer, but more detailed neurons
const CONNECTION_DISTANCE = 5.5; // Distance to form a synapse
const PULSE_SPEED = 2.5; // Speed of the electric signal

// 1. SINGLE NEURON CELL (The Soma)
// We use a distorted sphere to make it look like organic tissue
function NeuronCell({ position }: { position: [number, number, number] }) {
  const meshRef = useRef<THREE.Mesh>(null!);
  const [hovered, setHover] = useState(false);

  // Randomize size slightly for variety
  const scale = useMemo(() => 0.6 + Math.random() * 0.4, []);

  useFrame((state) => {
    // Gentle heartbeat pulsation
    const t = state.clock.getElapsedTime();
    const pulse = Math.sin(t * 3) * 0.05 + 1;
    if (meshRef.current) {
        meshRef.current.scale.set(scale * pulse, scale * pulse, scale * pulse);
    }
  });

  return (
    <Float speed={2} rotationIntensity={0.5} floatIntensity={0.5}>
      <Sphere
        ref={meshRef}
        args={[1, 32, 32]} // Geometry args
        position={position}
        onPointerOver={() => setHover(true)}
        onPointerOut={() => setHover(false)}
      >
        <MeshDistortMaterial
          color={hovered ? "#06b6d4" : "#22d3ee"} // Cyan 500 to 400
          emissive={hovered ? "#0891b2" : "#0e7490"}
          emissiveIntensity={0.6}
          roughness={0.2}
          metalness={0.1}
          distort={0.4} // The "wobble" amount (0-1)
          speed={2} // Speed of the wobble
        />
        <pointLight distance={3} intensity={2} color="#22d3ee" />
      </Sphere>
    </Float>
  );
}

// 2. SYNAPSE (The Connection & The Impulse)
// Draws a curved organic line and a traveling light pulse
function Synapse({ start, end }: { start: THREE.Vector3; end: THREE.Vector3 }) {
  const curve = useMemo(() => {
    // Create a quadratic bezier curve for a natural "tendon" look
    // Control point is midway but offset randomly to create the curve
    const mid = new THREE.Vector3().lerpVectors(start, end, 0.5);
    mid.x += (Math.random() - 0.5) * 2;
    mid.y += (Math.random() - 0.5) * 2;
    mid.z += (Math.random() - 0.5) * 2;
    return new THREE.QuadraticBezierCurve3(start, mid, end);
  }, [start, end]);

  // Create points for the line geometry
  const points = useMemo(() => curve.getPoints(20), [curve]);
  
  // The traveling impulse ref
  const impulseRef = useRef<THREE.Mesh>(null!);

  useFrame((state) => {
    // Move the impulse along the curve
    const t = (state.clock.getElapsedTime() * PULSE_SPEED) % 1; // 0 to 1 loop
    if (impulseRef.current) {
      const pos = curve.getPointAt(t);
      impulseRef.current.position.copy(pos);
      
      // Scale impulse based on position (fade in/out at ends)
      const scale = Math.sin(t * Math.PI); 
      impulseRef.current.scale.setScalar(scale * 0.15);
    }
  });

  return (
    <group>
      {/* The Axon (Line) */}
      <line>
        <bufferGeometry>
          <bufferAttribute
            attach="attributes-position"
            count={points.length}
            array={new Float32Array(points.flatMap((p) => [p.x, p.y, p.z]))}
            itemSize={3}
          />
        </bufferGeometry>
        <lineBasicMaterial
          color="#155e75" // Dark Cyan
          transparent
          opacity={0.3}
          linewidth={1} 
        />
      </line>

      {/* The Electric Impulse (Glowing Dot) */}
      <mesh ref={impulseRef}>
        <sphereGeometry args={[1, 8, 8]} />
        <meshBasicMaterial color="#ecfeff" toneMapped={false} />
        <pointLight distance={2} intensity={2} color="#22d3ee" decay={2} />
      </mesh>
    </group>
  );
}

// 3. MAIN SCENE CONTROLLER
function NeuralNetworkScene() {
  const { viewport } = useThree();
  const mouse = useRef(new THREE.Vector2());

  // Generate Neurons
  const neurons = useMemo(() => {
    const temp = [];
    for (let i = 0; i < NEURON_COUNT; i++) {
      temp.push({
        position: new THREE.Vector3(
          (Math.random() - 0.5) * 20,
          (Math.random() - 0.5) * 20,
          (Math.random() - 0.5) * 10
        ),
        id: i,
      });
    }
    return temp;
  }, []);

  // Generate Connections (Proximity based)
  const connections = useMemo(() => {
    const conns = [];
    for (let i = 0; i < neurons.length; i++) {
      for (let j = i + 1; j < neurons.length; j++) {
        const dist = neurons[i].position.distanceTo(neurons[j].position);
        if (dist < CONNECTION_DISTANCE) {
          conns.push({ start: neurons[i].position, end: neurons[j].position, key: `${i}-${j}` });
        }
      }
    }
    return conns;
  }, [neurons]);

  useFrame((state) => {
    // Soft camera movement based on mouse
    const x = (state.pointer.x * viewport.width) / 10;
    const y = (state.pointer.y * viewport.height) / 10;
    
    state.camera.position.x = THREE.MathUtils.lerp(state.camera.position.x, x, 0.05);
    state.camera.position.y = THREE.MathUtils.lerp(state.camera.position.y, y, 0.05);
    state.camera.lookAt(0, 0, 0);
  });

  return (
    <group>
      {/* Draw Neurons */}
      {neurons.map((n) => (
        <NeuronCell key={n.id} position={[n.position.x, n.position.y, n.position.z]} />
      ))}

      {/* Draw Synapses */}
      {connections.map((c) => (
        <Synapse key={c.key} start={c.start} end={c.end} />
      ))}
    </group>
  );
}

export default function BioNeurons() {
  return (
    <div className="absolute inset-0 z-0 h-full w-full">
      <Canvas
        camera={{ position: [0, 0, 14], fov: 45 }}
        gl={{ alpha: true, antialias: true }}
        dpr={[1, 2]}
      >
        <ambientLight intensity={0.2} />
        <pointLight position={[10, 10, 10]} intensity={1} color="#06b6d4" />
        <NeuralNetworkScene />
        <Preload all />
      </Canvas>
    </div>
  );
}