import { useRef, useState, Suspense, useEffect } from 'react';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, Environment, Stars, Effects } from '@react-three/drei';
import { Box, Disc, Hexagon, Octagon, Pentagon, Star, Palette, Zap, Maximize } from 'lucide-react';
import * as THREE from 'three';
import { EffectComposer, Bloom, ChromaticAberration } from '@react-three/postprocessing';

interface ShapeProps {
  geometry: 'box' | 'sphere' | 'torus' | 'icosahedron' | 'octahedron' | 'dodecahedron';
  color: string;
  textured: boolean;
  speed: number;
  scale: number;
  effects: boolean;
}

function createVoronoiTexture() {
  const size = 512;
  const data = new Uint8Array(size * size * 4);
  const points = Array(16).fill(0).map(() => ({
    x: Math.random() * size,
    y: Math.random() * size,
    color: Math.random() * 255
  }));

  for (let y = 0; y < size; y++) {
    for (let x = 0; x < size; x++) {
      let minDist = Infinity;
      let cellColor = 0;
      
      // Find nearest point for voronoi cell
      points.forEach(point => {
        const dx = x - point.x;
        const dy = y - point.y;
        const dist = dx * dx + dy * dy;
        if (dist < minDist) {
          minDist = dist;
          cellColor = point.color;
        }
      });

      // Add some noise to break up the pattern
      const noise = Math.random() * 30 - 15;
      const finalColor = Math.max(0, Math.min(255, cellColor + noise));
      
      const i = (y * size + x) * 4;
      data[i] = finalColor;     // r
      data[i + 1] = finalColor; // g
      data[i + 2] = finalColor; // b
      data[i + 3] = 255;        // a
    }
  }
  
  const texture = new THREE.DataTexture(data, size, size, THREE.RGBAFormat);
  texture.wrapS = THREE.RepeatWrapping;
  texture.wrapT = THREE.RepeatWrapping;
  texture.needsUpdate = true;
  return texture;
}

function Shape({ geometry, color, textured, speed, scale, effects }: ShapeProps) {
  const meshRef = useRef<THREE.Mesh>(null);
  const matRef = useRef<THREE.MeshPhysicalMaterial>(null);
  const [normalMap] = useState(() => createVoronoiTexture());
  
  useFrame((state, delta) => {
    if (meshRef.current) {
      meshRef.current.rotation.x += delta * speed;
      meshRef.current.rotation.y += delta * speed * 0.5;
    }
    if (matRef.current && effects) {
      matRef.current.roughness = Math.sin(state.clock.elapsedTime) * 0.3 + 0.5;
    }
  });

  const getGeometry = () => {
    switch (geometry) {
      case 'box':
        return <boxGeometry args={[1, 1, 1]} />;
      case 'sphere':
        return <sphereGeometry args={[0.7, 64, 64]} />;
      case 'torus':
        return <torusGeometry args={[0.7, 0.3, 64, 128]} />;
      case 'icosahedron':
        return <icosahedronGeometry args={[0.8, 1]} />;
      case 'octahedron':
        return <octahedronGeometry args={[0.8, 2]} />;
      case 'dodecahedron':
        return <dodecahedronGeometry args={[0.8, 1]} />;
      default:
        return <boxGeometry args={[1, 1, 1]} />;
    }
  };

  return (
    <mesh ref={meshRef} scale={scale} castShadow receiveShadow>
      {getGeometry()}
      <meshPhysicalMaterial
        ref={matRef}
        color={color}
        wireframe={!textured}
        roughness={textured ? 0.5 : 0}
        metalness={textured ? 0.9 : 0}
        clearcoat={textured ? 0.5 : 0}
        clearcoatRoughness={textured ? 0.2 : 0}
        normalMap={textured ? normalMap : null}
        normalScale={new THREE.Vector2(1.0, 1.0)}
        envMapIntensity={2.5}
        transmission={textured ? 0 : 0}
        thickness={0}
      />
    </mesh>
  );
}

function SceneContent(props: ShapeProps) {
  return (
    <>
      <color attach="background" args={['#000000']} />
      <fog attach="fog" args={['#000000', 5, 15]} />
      
      <ambientLight intensity={0.4} />
      <pointLight position={[10, 10, 10]} intensity={1} castShadow />
      <spotLight
        position={[-10, -10, -10]}
        angle={0.3}
        penumbra={1}
        intensity={2}
        castShadow
      />

      <Suspense fallback={null}>
        <Shape {...props} />
        <Environment preset="sunset" />
        <Stars radius={100} depth={50} count={5000} factor={4} saturation={0} fade speed={1} />
      </Suspense>

      {props.effects && (
        <EffectComposer>
          <Bloom 
            intensity={1.5}
            luminanceThreshold={0.8}
            luminanceSmoothing={0.5}
            height={200}
          />
          <ChromaticAberration offset={[0.001, 0.001]} />
        </EffectComposer>
      )}
      
      <OrbitControls makeDefault />
    </>
  );
}

export function Scene() {
  const [settings, setSettings] = useState({
    geometry: 'box' as const,
    color: '#ff6b6b',
    textured: false,
    speed: 1,
    scale: 1,
    effects: true,
  });

  const geometryOptions = [
    { value: 'box', label: 'Cube', icon: Box },
    { value: 'sphere', label: 'Sphere', icon: Disc },
    { value: 'torus', label: 'Torus', icon: Hexagon },
    { value: 'icosahedron', label: 'Icosahedron', icon: Pentagon },
    { value: 'octahedron', label: 'Octahedron', icon: Octagon },
    { value: 'dodecahedron', label: 'Dodecahedron', icon: Star },
  ];

  return (
    <div className="w-full h-screen flex bg-black">
      <div className="w-3/4 h-full">
        <Canvas
          camera={{ position: [3, 3, 3], fov: 50 }}
          shadows
          gl={{ antialias: true }}
          dpr={[1, 2]}
          className="w-full h-full"
        >
          <SceneContent {...settings} />
        </Canvas>
      </div>
      
      <div className="w-1/4 bg-gray-900 p-8 overflow-y-auto border-l border-gray-800">
        <h2 className="text-2xl font-bold mb-8 text-white flex items-center">
          <Palette className="w-6 h-6 mr-2" /> Scene Settings
        </h2>
        
        <div className="space-y-8">
          <div>
            <label className="block text-sm font-medium text-gray-300 mb-4 flex items-center">
              <Box className="w-4 h-4 mr-2" /> Geometry
            </label>
            <div className="grid grid-cols-2 gap-4">
              {geometryOptions.map((option) => {
                const Icon = option.icon;
                return (
                  <button
                    key={option.value}
                    onClick={() => setSettings({ ...settings, geometry: option.value as ShapeProps['geometry'] })}
                    className={`flex flex-col items-center justify-center p-4 rounded-lg transition-all ${
                      settings.geometry === option.value
                        ? 'bg-blue-600 text-white shadow-lg shadow-blue-500/30'
                        : 'bg-gray-800 text-gray-400 hover:bg-gray-700 hover:text-gray-200'
                    }`}
                  >
                    <Icon className="w-8 h-8 mb-2" strokeWidth={1.5} />
                    <span className="text-sm font-medium">{option.label}</span>
                  </button>
                );
              })}
            </div>
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-300 mb-3 flex items-center">
              <Palette className="w-4 h-4 mr-2" /> Color
            </label>
            <input
              type="color"
              value={settings.color}
              onChange={(e) => setSettings({ ...settings, color: e.target.value })}
              className="w-full h-12 rounded-lg cursor-pointer bg-gray-800 border-2 border-gray-700"
            />
          </div>

          <div className="flex items-center justify-between">
            <div className="flex items-center space-x-3">
              <label className="text-sm font-medium text-gray-300 flex items-center">
                <Zap className="w-4 h-4 mr-2" /> Effects
              </label>
              <button
                onClick={() => setSettings({ ...settings, effects: !settings.effects })}
                className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
                  settings.effects ? 'bg-blue-600' : 'bg-gray-700'
                }`}
              >
                <span
                  className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                    settings.effects ? 'translate-x-6' : 'translate-x-1'
                  }`}
                />
              </button>
            </div>

            <div className="flex items-center space-x-3">
              <label className="text-sm font-medium text-gray-300 flex items-center">
                Metallic
              </label>
              <button
                onClick={() => setSettings({ ...settings, textured: !settings.textured })}
                className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${
                  settings.textured ? 'bg-blue-600' : 'bg-gray-700'
                }`}
              >
                <span
                  className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                    settings.textured ? 'translate-x-6' : 'translate-x-1'
                  }`}
                />
              </button>
            </div>
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-300 mb-3 flex items-center">
              <Zap className="w-4 h-4 mr-2" /> Rotation Speed: {settings.speed.toFixed(1)}
            </label>
            <input
              type="range"
              min="0"
              max="5"
              step="0.1"
              value={settings.speed}
              onChange={(e) => setSettings({ ...settings, speed: parseFloat(e.target.value) })}
              className="w-full accent-blue-600 bg-gray-700 h-2 rounded-lg appearance-none cursor-pointer"
            />
          </div>

          <div>
            <label className="block text-sm font-medium text-gray-300 mb-3 flex items-center">
              <Maximize className="w-4 h-4 mr-2" /> Scale: {settings.scale.toFixed(1)}
            </label>
            <input
              type="range"
              min="0.1"
              max="3"
              step="0.1"
              value={settings.scale}
              onChange={(e) => setSettings({ ...settings, scale: parseFloat(e.target.value) })}
              className="w-full accent-blue-600 bg-gray-700 h-2 rounded-lg appearance-none cursor-pointer"
            />
          </div>
        </div>
      </div>
    </div>
  );
}