
import React, { useRef, useMemo, useEffect } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, PerspectiveCamera } from '@react-three/drei';
import * as THREE from 'three';

// Add global declaration to fix TypeScript errors with React Three Fiber elements
declare module 'react' {
  namespace JSX {
    interface IntrinsicElements {
      points: any;
      bufferGeometry: any;
      bufferAttribute: any;
      pointsMaterial: any;
      ambientLight: any;
    }
  }
}

declare global {
  namespace JSX {
    interface IntrinsicElements {
      points: any;
      bufferGeometry: any;
      bufferAttribute: any;
      pointsMaterial: any;
      ambientLight: any;
    }
  }
}

interface TechVisualizerProps {
  mode: 'server' | 'monitor' | 'hidden';
}

const ParticleMorph = ({ mode }: { mode: 'server' | 'monitor' | 'hidden' }) => {
  const meshRef = useRef<THREE.Points>(null);
  const COUNT = 3000;
  
  // Define geometries
  const data = useMemo(() => {
    const pos = new Float32Array(COUNT * 3);
    const col = new Float32Array(COUNT * 3);
    const serverPos = new Float32Array(COUNT * 3);
    const monitorPos = new Float32Array(COUNT * 3);

    // SERVER SHAPE (Rectangular Tower)
    for (let i = 0; i < COUNT; i++) {
        const x = (Math.random() - 0.5) * 2; // Thin width
        const y = (Math.random() - 0.5) * 6; // Tall
        const z = (Math.random() - 0.5) * 2; // Depth
        
        serverPos[i * 3] = x;
        serverPos[i * 3 + 1] = y;
        serverPos[i * 3 + 2] = z;

        // Add some "layers" to make it look like a rack
        if (Math.random() > 0.8) {
            serverPos[i * 3] *= 1.2;
            serverPos[i * 3 + 2] *= 1.2;
        }
    }

    // MONITOR SHAPE (Curved Plane)
    for (let i = 0; i < COUNT; i++) {
        const x = (Math.random() - 0.5) * 8; // Wide
        const y = (Math.random() - 0.5) * 3.5; // Aspect ratio
        // Curve the Z based on X (parabolic)
        const z = Math.pow(x * 0.3, 2) - 2; 

        monitorPos[i * 3] = x;
        monitorPos[i * 3 + 1] = y + 0.5; // Lift up slightly
        monitorPos[i * 3 + 2] = z;

        // Bezel/Frame particles
        if (Math.random() > 0.95) {
             monitorPos[i * 3 + 2] += 0.1;
        }
    }

    // Initial Positions (start at server)
    for (let i = 0; i < COUNT * 3; i++) {
        pos[i] = serverPos[i];
        col[i] = 1; // Initial white/cyan mix logic in shader or simple color
    }
    
    return { positions: pos, colors: col, serverPos, monitorPos };
  }, []);

  // Buffer attributes
  const bufferRef = useRef<THREE.BufferAttribute>(null);

  useFrame((state, delta) => {
    if (!meshRef.current || !bufferRef.current) return;
    
    const target = mode === 'monitor' ? data.monitorPos : data.serverPos;
    const current = bufferRef.current.array as Float32Array;
    
    // Morph speed
    const speed = 4 * delta;

    // Visibility transition
    const isHidden = mode === 'hidden';
    
    for (let i = 0; i < COUNT; i++) {
        const ix = i * 3;
        const iy = i * 3 + 1;
        const iz = i * 3 + 2;

        if (isHidden) {
            // Explode/Hide
            current[ix] = THREE.MathUtils.lerp(current[ix], current[ix] * 1.01, speed);
            current[iy] = THREE.MathUtils.lerp(current[iy], current[iy] + 10, speed);
        } else {
             // Standard Morph
            current[ix] = THREE.MathUtils.lerp(current[ix], target[ix], speed);
            current[iy] = THREE.MathUtils.lerp(current[iy], target[iy], speed);
            current[iz] = THREE.MathUtils.lerp(current[iz], target[iz], speed);

            // Add subtle noise/floating
            current[iy] += Math.sin(state.clock.elapsedTime + current[ix]) * 0.002;
        }
    }
    
    bufferRef.current.needsUpdate = true;
    
    // Rotate entire mesh slowly
    meshRef.current.rotation.y += delta * 0.1;
  });

  return (
    <points ref={meshRef}>
      <bufferGeometry>
        <bufferAttribute
          ref={bufferRef}
          attach="attributes-position"
          array={data.positions}
          count={data.positions.length / 3}
          itemSize={3}
        />
      </bufferGeometry>
      <pointsMaterial
        size={0.04}
        color={mode === 'monitor' ? "#ff4b4b" : "#20e3b2"} // Red for monitor (Anime.js accent), Cyan for Server
        transparent
        opacity={0.8}
        sizeAttenuation
        blending={THREE.AdditiveBlending}
      />
    </points>
  );
};

const TechVisualizer: React.FC<TechVisualizerProps> = ({ mode }) => {
  return (
    <div className={`fixed inset-0 z-[1] transition-opacity duration-700 pointer-events-none ${mode === 'hidden' ? 'opacity-0' : 'opacity-60'}`}>
        <Canvas gl={{ antialias: true, alpha: true }}>
            <PerspectiveCamera makeDefault position={[0, 0, 8]} fov={50} />
            <ambientLight intensity={0.5} />
            <ParticleMorph mode={mode} />
        </Canvas>
    </div>
  );
};

export default TechVisualizer;
