import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, Stars, Line, Sphere } from '@react-three/drei';
import { useMemo, useRef } from 'react';
import * as THREE from 'three';
import { Agent } from '../../../types';

function LaserPulse({ start, end, color }: { start: [number, number, number], end: [number, number, number], color: string }) {
  const meshRef = useRef<THREE.Mesh>(null);
  useFrame((state) => {
    if (meshRef.current) {
      // Move pulse from start to end
      const t = (state.clock.elapsedTime * 2) % 1;
      meshRef.current.position.set(
        start[0] + (end[0] - start[0]) * t,
        start[1] + (end[1] - start[1]) * t,
        start[2] + (end[2] - start[2]) * t
      );
    }
  });

  return (
    <mesh ref={meshRef}>
      <sphereGeometry args={[0.08, 8, 8]} />
      <meshBasicMaterial color={color} />
    </mesh>
  );
}

const STALE_THRESHOLD_MS = 5 * 60 * 1000;

function AgentNode({ agent, position, serverPos }: { agent: Agent, position: [number, number, number], serverPos: [number, number, number] }) {
  const isOnline = agent.status === 'online';
  const isHashing = agent.hashrate_15m > 0;
  const color = isOnline ? (isHashing ? '#00f5ff' : '#00aa55') : '#ff4444';
  const pulseRef = useRef<THREE.Mesh>(null);
  const ringRef = useRef<THREE.Mesh>(null);

  // Stale = online status but last_seen older than 5 min (silently dead)
  const isStale = isOnline && !!agent.last_seen &&
    (Date.now() - new Date(agent.last_seen).getTime()) > STALE_THRESHOLD_MS;

  useFrame((state) => {
    if (isOnline && pulseRef.current) {
      const scale = 1 + Math.sin(state.clock.elapsedTime * (isHashing ? 5 : 1)) * 0.15 * (isHashing ? 1 : 0.5);
      pulseRef.current.scale.set(scale, scale, scale);
      if (isHashing) {
        pulseRef.current.rotation.y += 0.05;
        pulseRef.current.rotation.x += 0.05;
      }
    }
    // Slowly spin the staleness warning ring
    if (isStale && ringRef.current) {
      ringRef.current.rotation.z += 0.01;
      ringRef.current.rotation.x = Math.sin(state.clock.elapsedTime * 0.5) * 0.3;
    }
  });

  return (
    <group position={position}>
      <Sphere ref={pulseRef} args={[0.3, 16, 16]}>
        <meshStandardMaterial color={color} emissive={color} emissiveIntensity={isOnline ? (isHashing ? 2 : 1) : 0.2} wireframe />
      </Sphere>

      {/* Staleness warning ring — amber halo for online-but-silent nodes */}
      {isStale && (
        <mesh ref={ringRef}>
          <torusGeometry args={[0.55, 0.04, 8, 40]} />
          <meshBasicMaterial color="#ffb020" opacity={0.85} transparent />
        </mesh>
      )}

      {/* Connection Line */}
      <Line points={[[0,0,0], [serverPos[0] - position[0], serverPos[1] - position[1], serverPos[2] - position[2]]]} color={isStale ? '#665500' : isOnline ? '#004455' : '#330000'} lineWidth={1} transparent opacity={0.4} />
      
      {/* Laser Pulse simulating hashing packets */}
      {isOnline && isHashing && !isStale && (
        <LaserPulse start={[0,0,0]} end={[serverPos[0] - position[0], serverPos[1] - position[1], serverPos[2] - position[2]]} color="#00ffff" />
      )}
    </group>
  );
}

export default function FleetTopologyMap({ agents }: { agents: Agent[] }) {
  const serverPos: [number, number, number] = [0, 0, 0];

  const agentNodes = useMemo(() => {
    return agents.map((agent, i) => {
      const goldenRatio = (1 + Math.sqrt(5)) / 2;
      const angle = i * Math.PI * 2 * goldenRatio;
      // Distribute in a spherical/cylindrical rough cluster
      const radius = 4 + Math.random() * 3 + (i * 0.05);
      const x = Math.cos(angle) * radius;
      const z = Math.sin(angle) * radius;
      const y = (Math.random() - 0.5) * 6;
      return { agent, position: [x, y, z] as [number, number, number] };
    });
  }, [agents]);

  return (
    <div className="topology-container" style={{ width: '100%', height: '500px', background: '#050508', borderRadius: '8px', overflow: 'hidden', border: '1px solid var(--neon-cyan)', position: 'relative', boxShadow: '0 0 20px rgba(0, 245, 255, 0.1)' }}>
      <div style={{ position: 'absolute', top: 15, left: 15, zIndex: 10, color: 'var(--neon-cyan)', fontFamily: 'monospace', textShadow: '0 0 5px var(--neon-cyan)' }}>
        <span className="live-beacon on" style={{ display: 'inline-block', marginRight: 8, verticalAlign: 'middle' }}></span>
        3D_MESH_TOPOLOGY // {agents.filter(a => a.status === 'online').length} NODES LINKED
      </div>
      <Canvas camera={{ position: [0, 8, 14], fov: 50 }}>
        <color attach="background" args={['#050508']} />
        <ambientLight intensity={0.5} />
        <pointLight position={[10, 10, 10]} intensity={1.5} color="#00f5ff" />
        <Stars radius={100} depth={50} count={3000} factor={3} saturation={0.5} fade speed={1} />
        
        {/* Server Node (Mothership) */}
        <group position={serverPos}>
          <Sphere args={[0.7, 32, 32]}>
            <meshStandardMaterial color="#ffb020" emissive="#ffb020" emissiveIntensity={1.2} wireframe />
          </Sphere>
          <Sphere args={[0.3, 16, 16]}>
            <meshStandardMaterial color="#ffffff" emissive="#ffffff" emissiveIntensity={2} />
          </Sphere>
        </group>

        {/* Agent Nodes */}
        {agentNodes.map((node) => (
          <AgentNode key={node.agent.id} agent={node.agent} position={node.position} serverPos={serverPos} />
        ))}

        <OrbitControls enablePan={true} enableZoom={true} enableRotate={true} autoRotate autoRotateSpeed={0.8} />
      </Canvas>
    </div>
  );
}