/**
 * VEZA V5 ULTRA - 3D AUDIO VISUALIZER
 * Interactive 3D visualization using Three.js and Web Audio API
 */

import { useEffect, useRef, useState } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls } from '@react-three/drei';
import * as THREE from 'three';
import type { AudioAnalysis } from '@/services/audio-engine-v5';

interface VisualizerBarsProps {
  frequencyData: Uint8Array;
  barCount?: number;
}

function VisualizerBars({ frequencyData, barCount = 64 }: VisualizerBarsProps) {
  const groupRef = useRef<THREE.Group>(null);
  const barsRef = useRef<THREE.Mesh[]>([]);
  
  // Create bars on mount
  useEffect(() => {
    if (!groupRef.current) return;
    
    const bars: THREE.Mesh[] = [];
    const radius = 5;
    
    for (let i = 0; i < barCount; i++) {
      const geometry = new THREE.BoxGeometry(0.2, 1, 0.2);
      const material = new THREE.MeshStandardMaterial({
        color: new THREE.Color().setHSL(i / barCount, 1, 0.5),
        emissive: new THREE.Color().setHSL(i / barCount, 1, 0.3),
        metalness: 0.5,
        roughness: 0.2,
      });
      
      const bar = new THREE.Mesh(geometry, material);
      
      const angle = (i / barCount) * Math.PI * 2;
      bar.position.x = Math.cos(angle) * radius;
      bar.position.z = Math.sin(angle) * radius;
      bar.rotation.y = -angle;
      
      groupRef.current.add(bar);
      bars.push(bar);
    }
    
    barsRef.current = bars;
    
    return () => {
      bars.forEach(bar => {
        bar.geometry.dispose();
        (bar.material as THREE.Material).dispose();
      });
    };
  }, [barCount]);
  
  // Animate bars based on frequency data
  useFrame(() => {
    if (!barsRef.current.length || !frequencyData.length) return;
    
    const dataStep = Math.floor(frequencyData.length / barCount);
    
    barsRef.current.forEach((bar, i) => {
      const dataIndex = i * dataStep;
      const value = frequencyData[dataIndex] / 255;
      
      // Smooth scaling
      const targetScale = 0.5 + value * 5;
      bar.scale.y += (targetScale - bar.scale.y) * 0.2;
      
      // Update color based on intensity
      const material = bar.material as THREE.MeshStandardMaterial;
      const hue = i / barCount;
      material.emissive.setHSL(hue, 1, value * 0.5);
      
      // Pulse effect
      bar.position.y = bar.scale.y / 2;
    });
    
    // Rotate the entire group slowly
    if (groupRef.current) {
      groupRef.current.rotation.y += 0.002;
    }
  });
  
  return <group ref={groupRef} />;
}

interface ParticlesProps {
  frequencyData: Uint8Array;
  particleCount?: number;
}

function Particles({ frequencyData, particleCount = 1000 }: ParticlesProps) {
  const pointsRef = useRef<THREE.Points>(null);
  const positionsRef = useRef<Float32Array | null>(null);
  
  useEffect(() => {
    if (!pointsRef.current) return;
    
    const positions = new Float32Array(particleCount * 3);
    
    for (let i = 0; i < particleCount; i++) {
      const i3 = i * 3;
      const radius = 2 + Math.random() * 8;
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.random() * Math.PI;
      
      positions[i3] = radius * Math.sin(phi) * Math.cos(theta);
      positions[i3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
      positions[i3 + 2] = radius * Math.cos(phi);
    }
    
    positionsRef.current = positions;
    pointsRef.current.geometry.setAttribute(
      'position',
      new THREE.BufferAttribute(positions, 3)
    );
  }, [particleCount]);
  
  useFrame(({ clock }) => {
    if (!pointsRef.current || !positionsRef.current) return;
    
    const positions = pointsRef.current.geometry.attributes.position.array as Float32Array;
    const time = clock.getElapsedTime();
    
    // Calculate average energy from frequency data
    const avgEnergy = frequencyData.length > 0
      ? Array.from(frequencyData).reduce((a, b) => a + b, 0) / frequencyData.length / 255
      : 0;
    
    for (let i = 0; i < particleCount; i++) {
      const i3 = i * 3;
      
      // Pulsate based on audio energy
      const scale = 1 + avgEnergy * 0.5;
      positions[i3] = positionsRef.current[i3] * scale;
      positions[i3 + 1] = positionsRef.current[i3 + 1] * scale + Math.sin(time + i) * 0.1;
      positions[i3 + 2] = positionsRef.current[i3 + 2] * scale;
    }
    
    pointsRef.current.geometry.attributes.position.needsUpdate = true;
    pointsRef.current.rotation.y += 0.001;
  });
  
  return (
    <points ref={pointsRef}>
      <bufferGeometry />
      <pointsMaterial
        size={0.05}
        color="#667eea"
        transparent
        opacity={0.6}
        sizeAttenuation
      />
    </points>
  );
}

interface AudioVisualizer3DProps {
  analysis: AudioAnalysis | null;
  mode?: 'bars' | 'particles' | 'hybrid';
  className?: string;
}

export function AudioVisualizer3D({ 
  analysis, 
  mode = 'hybrid',
  className = ''
}: AudioVisualizer3DProps) {
  const [frequencyData, setFrequencyData] = useState<Uint8Array>(new Uint8Array(0));
  
  useEffect(() => {
    if (analysis?.frequencyData) {
      setFrequencyData(analysis.frequencyData);
    }
  }, [analysis]);
  
  return (
    <div className={`w-full h-full ${className}`}>
      <Canvas
        camera={{ position: [0, 5, 15], fov: 60 }}
        gl={{ 
          antialias: true, 
          alpha: true,
          powerPreference: 'high-performance'
        }}
      >
        {/* Lighting */}
        <ambientLight intensity={0.5} />
        <pointLight position={[10, 10, 10]} intensity={1} />
        <pointLight position={[-10, -10, -10]} intensity={0.5} color="#764ba2" />
        
        {/* Visualizations */}
        {(mode === 'bars' || mode === 'hybrid') && (
          <VisualizerBars frequencyData={frequencyData} barCount={64} />
        )}
        
        {(mode === 'particles' || mode === 'hybrid') && (
          <Particles frequencyData={frequencyData} particleCount={500} />
        )}
        
        {/* Controls */}
        <OrbitControls
          enableZoom={true}
          enablePan={false}
          minDistance={10}
          maxDistance={30}
          autoRotate
          autoRotateSpeed={0.5}
        />
      </Canvas>
    </div>
  );
}

// Mini visualizer for player
interface MiniVisualizerProps {
  analysis: AudioAnalysis | null;
  className?: string;
  barCount?: number;
}

export function MiniVisualizer({ 
  analysis, 
  className = '',
  barCount = 32
}: MiniVisualizerProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  
  useEffect(() => {
    if (!canvasRef.current || !analysis) return;
    
    const canvas = canvasRef.current;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    
    const draw = () => {
      const { width, height } = canvas;
      ctx.clearRect(0, 0, width, height);
      
      if (!analysis.frequencyData.length) return;
      
      const barWidth = width / barCount;
      const dataStep = Math.floor(analysis.frequencyData.length / barCount);
      
      for (let i = 0; i < barCount; i++) {
        const dataIndex = i * dataStep;
        const value = analysis.frequencyData[dataIndex] / 255;
        const barHeight = value * height;
        
        const x = i * barWidth;
        const y = height - barHeight;
        
        // Gradient based on position
        const gradient = ctx.createLinearGradient(x, y, x, height);
        gradient.addColorStop(0, '#667eea');
        gradient.addColorStop(1, '#764ba2');
        
        ctx.fillStyle = gradient;
        ctx.fillRect(x, y, barWidth - 2, barHeight);
      }
      
      requestAnimationFrame(draw);
    };
    
    draw();
  }, [analysis, barCount]);
  
  return (
    <canvas
      ref={canvasRef}
      className={`w-full h-full ${className}`}
      width={300}
      height={60}
    />
  );
}

