import * as THREE from 'three';

export function createStarfield(scene) {
  const starCount = 12000;
  const starDistance = 300;
  
  // Create geometry for stars
  const starGeometry = new THREE.BufferGeometry();
  const starPositions = new Float32Array(starCount * 3);
  const starSizes = new Float32Array(starCount);
  
  // Store original positions, current positions, and sizes
  const originalPositions = new Float32Array(starCount * 3);
  const currentPositions = new Float32Array(starCount * 3);
  const originalSizes = new Float32Array(starCount);
  const currentSizes = new Float32Array(starCount);
  
  // Generate random positions in a sphere around the scene
  for (let i = 0; i < starCount; i++) {
    const i3 = i * 3;
    
    const radius = Math.random() * starDistance + 50;
    const theta = Math.random() * Math.PI * 2;
    const phi = Math.acos(2 * Math.random() - 1);
    
    const x = radius * Math.sin(phi) * Math.cos(theta);
    const y = radius * Math.sin(phi) * Math.sin(theta);
    const z = radius * Math.cos(phi);
    
    // Store both original and current positions
    originalPositions[i3] = x;
    originalPositions[i3 + 1] = y;
    originalPositions[i3 + 2] = z;
    
    currentPositions[i3] = x;
    currentPositions[i3 + 1] = y;
    currentPositions[i3 + 2] = z;
    
    starPositions[i3] = x;
    starPositions[i3 + 1] = y;
    starPositions[i3 + 2] = z;
    
    // Store original and current sizes
    const baseSize = Math.random() * 0.2 + 0.1;
    originalSizes[i] = baseSize;
    currentSizes[i] = baseSize;
    starSizes[i] = baseSize;
  }

  starGeometry.setAttribute('position', new THREE.BufferAttribute(starPositions, 3));
  starGeometry.setAttribute('size', new THREE.BufferAttribute(starSizes, 1));

  // Star material with size attenuation
  const starMaterial = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.3,
    sizeAttenuation: true,
    transparent: true,
    opacity: 0.8,
    vertexColors: false
  });

  const stars = new THREE.Points(starGeometry, starMaterial);
  scene.add(stars);

  // Distant stars layer
  const distantStarCount = 4000;
  const distantStarGeometry = new THREE.BufferGeometry();
  const distantStarPositions = new Float32Array(distantStarCount * 3);
  const distantStarSizes = new Float32Array(distantStarCount);
  const distantOriginalPositions = new Float32Array(distantStarCount * 3);
  const distantCurrentPositions = new Float32Array(distantStarCount * 3);
  const distantOriginalSizes = new Float32Array(distantStarCount);
  const distantCurrentSizes = new Float32Array(distantStarCount);

  for (let i = 0; i < distantStarCount; i++) {
    const i3 = i * 3;
    
    const radius = Math.random() * 200 + starDistance;
    const theta = Math.random() * Math.PI * 2;
    const phi = Math.acos(2 * Math.random() - 1);
    
    const x = radius * Math.sin(phi) * Math.cos(theta);
    const y = radius * Math.sin(phi) * Math.sin(theta);
    const z = radius * Math.cos(phi);
    
    distantOriginalPositions[i3] = x;
    distantOriginalPositions[i3 + 1] = y;
    distantOriginalPositions[i3 + 2] = z;
    
    distantCurrentPositions[i3] = x;
    distantCurrentPositions[i3 + 1] = y;
    distantCurrentPositions[i3 + 2] = z;
    
    distantStarPositions[i3] = x;
    distantStarPositions[i3 + 1] = y;
    distantStarPositions[i3 + 2] = z;
    
    // Store original and current sizes for distant stars
    const baseSize = Math.random() * 0.1 + 0.05;
    distantOriginalSizes[i] = baseSize;
    distantCurrentSizes[i] = baseSize;
    distantStarSizes[i] = baseSize;
  }

  distantStarGeometry.setAttribute('position', new THREE.BufferAttribute(distantStarPositions, 3));
  distantStarGeometry.setAttribute('size', new THREE.BufferAttribute(distantStarSizes, 1));

  const distantStarMaterial = new THREE.PointsMaterial({
    color: 0xccccff,
    size: 0.15,
    sizeAttenuation: true,
    transparent: true,
    opacity: 0.4
  });

  const distantStars = new THREE.Points(distantStarGeometry, distantStarMaterial);
  scene.add(distantStars);

  // Animation parameters
  const movementAmplitude = 2;
  const repulsionRadius = 400;
  const repulsionStrength = 5;
  const interpolationSpeed = 5;
  
  // NEW: Cursor brightness parameters
  const brightnessRadius = 600; // Radius for size increase effect
  const maxSizeMultiplier = 400.0; // Maximum size increase (4x original size)
  const sizeInterpolationSpeed = 100.0; // Speed of size changes
  
  // Raycaster for mouse position in 3D space
  const raycaster = new THREE.Raycaster();
  const mouseWorldPos = new THREE.Vector3();
  
  function animateStars(camera, mouse, deltaTime) {
    const time = Date.now() * 0.0003;
    
    // Get mouse position in world space
    if (mouse && camera) {
      raycaster.setFromCamera(mouse, camera);
      // Project mouse to a plane at distance 0 from camera
      const distance = 100;
      mouseWorldPos.copy(raycaster.ray.direction).multiplyScalar(distance).add(raycaster.ray.origin);
    }
    
    // Update close stars
    const positions = starGeometry.attributes.position.array;
    const sizes = starGeometry.attributes.size.array;
    
    for (let i = 0; i < starCount; i++) {
      const i3 = i * 3;
      
      // Get original position
      const origX = originalPositions[i3];
      const origY = originalPositions[i3 + 1];
      const origZ = originalPositions[i3 + 2];
      
      // Add gentle oscillating movement
      const offsetX = Math.sin(time + i * 0.01) * movementAmplitude;
      const offsetY = Math.cos(time * 0.7 + i * 0.02) * movementAmplitude;
      const offsetZ = Math.sin(time * 0.5 + i * 0.015) * movementAmplitude;
      
      let targetX = origX + offsetX;
      let targetY = origY + offsetY;
      let targetZ = origZ + offsetZ;
      
      // Cursor repulsion
      if (mouse) {
        const dx = targetX - mouseWorldPos.x;
        const dy = targetY - mouseWorldPos.y;
        const dz = targetZ - mouseWorldPos.z;
        const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        
        if (distance < repulsionRadius && distance > 0) {
          const force = (1 - distance / repulsionRadius) * repulsionStrength;
          const nx = dx / distance;
          const ny = dy / distance;
          const nz = dz / distance;
          
          targetX += nx * force;
          targetY += ny * force;
          targetZ += nz * force;
        }
      }
      
      // Smooth interpolation to target position
      const currentX = currentPositions[i3];
      const currentY = currentPositions[i3 + 1];
      const currentZ = currentPositions[i3 + 2];
      
      const lerpFactor = Math.min(interpolationSpeed * deltaTime, 1.0);
      
      currentPositions[i3] = THREE.MathUtils.lerp(currentX, targetX, lerpFactor);
      currentPositions[i3 + 1] = THREE.MathUtils.lerp(currentY, targetY, lerpFactor);
      currentPositions[i3 + 2] = THREE.MathUtils.lerp(currentZ, targetZ, lerpFactor);
      
      // Update geometry positions
      positions[i3] = currentPositions[i3];
      positions[i3 + 1] = currentPositions[i3 + 1];
      positions[i3 + 2] = currentPositions[i3 + 2];
      
      // NEW: Calculate size based on cursor proximity
      let targetSize = originalSizes[i];
      
      if (mouse) {
        const finalX = currentPositions[i3];
        const finalY = currentPositions[i3 + 1];
        const finalZ = currentPositions[i3 + 2];
        
        const dx = finalX - mouseWorldPos.x;
        const dy = finalY - mouseWorldPos.y;
        const dz = finalZ - mouseWorldPos.z;
        const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        
        if (distance < brightnessRadius) {
          // Calculate size multiplier based on distance (closer = bigger)
          const proximityFactor = 1 - (distance / brightnessRadius);
          const sizeMultiplier = 1 + (proximityFactor * (maxSizeMultiplier - 1));
          targetSize = originalSizes[i] * sizeMultiplier;
        }
      }
      
      // Smooth interpolation for size changes
      const sizeLerpFactor = Math.min(sizeInterpolationSpeed * deltaTime, 1.0);
      currentSizes[i] = THREE.MathUtils.lerp(currentSizes[i], targetSize, sizeLerpFactor);
      sizes[i] = currentSizes[i];
    }
    
    // Update distant stars (less affected by cursor)
    const distantPositions = distantStarGeometry.attributes.position.array;
    const distantSizes = distantStarGeometry.attributes.size.array;
    
    for (let i = 0; i < distantStarCount; i++) {
      const i3 = i * 3;
      
      const origX = distantOriginalPositions[i3];
      const origY = distantOriginalPositions[i3 + 1];
      const origZ = distantOriginalPositions[i3 + 2];
      
      // Gentler movement for distant stars
      const offsetX = Math.sin(time * 0.5 + i * 0.005) * movementAmplitude * 0.3;
      const offsetY = Math.cos(time * 0.3 + i * 0.008) * movementAmplitude * 0.3;
      const offsetZ = Math.sin(time * 0.4 + i * 0.006) * movementAmplitude * 0.3;
      
      let targetX = origX + offsetX;
      let targetY = origY + offsetY;
      let targetZ = origZ + offsetZ;
      
      // Weaker cursor repulsion for distant stars
      if (mouse) {
        const dx = targetX - mouseWorldPos.x;
        const dy = targetY - mouseWorldPos.y;
        const dz = targetZ - mouseWorldPos.z;
        const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        
        if (distance < repulsionRadius * 1.5 && distance > 0) {
          const force = (1 - distance / (repulsionRadius * 1.5)) * repulsionStrength * 0.3;
          const nx = dx / distance;
          const ny = dy / distance;
          const nz = dz / distance;
          
          targetX += nx * force;
          targetY += ny * force;
          targetZ += nz * force;
        }
      }
      
      // Smooth interpolation for positions
      const currentX = distantCurrentPositions[i3];
      const currentY = distantCurrentPositions[i3 + 1];
      const currentZ = distantCurrentPositions[i3 + 2];
      
      const lerpFactor = Math.min(interpolationSpeed * deltaTime * 0.7, 1.0);
      
      distantCurrentPositions[i3] = THREE.MathUtils.lerp(currentX, targetX, lerpFactor);
      distantCurrentPositions[i3 + 1] = THREE.MathUtils.lerp(currentY, targetY, lerpFactor);
      distantCurrentPositions[i3 + 2] = THREE.MathUtils.lerp(currentZ, targetZ, lerpFactor);
      
      distantPositions[i3] = distantCurrentPositions[i3];
      distantPositions[i3 + 1] = distantCurrentPositions[i3 + 1];
      distantPositions[i3 + 2] = distantCurrentPositions[i3 + 2];
      
      // NEW: Size effect for distant stars (weaker)
      let targetSize = distantOriginalSizes[i];
      
      if (mouse) {
        const finalX = distantCurrentPositions[i3];
        const finalY = distantCurrentPositions[i3 + 1];
        const finalZ = distantCurrentPositions[i3 + 2];
        
        const dx = finalX - mouseWorldPos.x;
        const dy = finalY - mouseWorldPos.y;
        const dz = finalZ - mouseWorldPos.z;
        const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        
        if (distance < brightnessRadius * 1.2) {
          // Weaker effect for distant stars
          const proximityFactor = 1 - (distance / (brightnessRadius * 1.2));
          const sizeMultiplier = 1 + (proximityFactor * (maxSizeMultiplier * 0.5 - 1));
          targetSize = distantOriginalSizes[i] * sizeMultiplier;
        }
      }
      
      // Smooth interpolation for distant star sizes
      const sizeLerpFactor = Math.min(sizeInterpolationSpeed * deltaTime * 0.8, 1.0);
      distantCurrentSizes[i] = THREE.MathUtils.lerp(distantCurrentSizes[i], targetSize, sizeLerpFactor);
      distantSizes[i] = distantCurrentSizes[i];
    }
    
    // Mark geometry for update
    starGeometry.attributes.position.needsUpdate = true;
    starGeometry.attributes.size.needsUpdate = true;
    distantStarGeometry.attributes.position.needsUpdate = true;
    distantStarGeometry.attributes.size.needsUpdate = true;
    
    // Subtle twinkling
    starMaterial.opacity = 0.6 + Math.sin(time * 2) * 0.2;
    distantStarMaterial.opacity = 0.3 + Math.sin(time * 1.5 + 1) * 0.1;
  }

  return {
    stars,
    distantStars,
    animateStars,
    starMaterial,
    distantStarMaterial
  };
}
