import * as THREE from 'three'
import * as CANNON from 'cannon-es'

export class PhysicsManager {
  static setupPhysicsWorld(): CANNON.World {
    const world = new CANNON.World()
    
    // Setup physics world
    world.gravity.set(0, 0, 0)
    
    // Use SAPBroadphase for better collision detection with many objects
    world.broadphase = new CANNON.SAPBroadphase(world)
    
    // Enable collision detection and response
    world.allowSleep = false // Prevent objects from sleeping
    
    // Configure contact material for better collisions
    const defaultMaterial = new CANNON.Material('default')
    const defaultContactMaterial = new CANNON.ContactMaterial(defaultMaterial, defaultMaterial, {
      friction: 0.4,
      restitution: 0.3,
      contactEquationStiffness: 1e8,
      contactEquationRelaxation: 3,
      frictionEquationStiffness: 1e8,
      frictionEquationRelaxation: 3
    })
    world.addContactMaterial(defaultContactMaterial)
    world.defaultMaterial = defaultMaterial

    return world
  }

  static updatePhysics(
    world: CANNON.World,
    physicsObjects: Array<{ mesh: THREE.Object3D; body: CANNON.Body }>,
    attractionPoint: THREE.Vector3,
    mouseWorldPosition: THREE.Vector3,
    deltaTime: number
  ): void {
    // Use a smaller, more stable timestep for better collision detection
    const fixedTimeStep = 1/60 // 60 Hz - more stable than 120 Hz
    const maxSubSteps = 5 // Increased substeps for better collision accuracy
    
    world.step(fixedTimeStep, deltaTime, maxSubSteps)

    // Apply forces to objects
    physicsObjects.forEach((obj) => {
      // Attraction to center point
      const attractionForce = new CANNON.Vec3()
      attractionForce.x = attractionPoint.x - obj.body.position.x
      attractionForce.y = attractionPoint.y - obj.body.position.y
      attractionForce.z = attractionPoint.z - obj.body.position.z
      
      const distance = Math.sqrt(
        attractionForce.x * attractionForce.x +
        attractionForce.y * attractionForce.y +
        attractionForce.z * attractionForce.z
      )
      
      if (distance > 0) {
        const strength = 16.0 / (distance * distance + 1) // Reduced from 8.0 to prevent objects moving too fast
        attractionForce.scale(strength, attractionForce)
        obj.body.force.set(
          obj.body.force.x + attractionForce.x,
          obj.body.force.y + attractionForce.y,
          obj.body.force.z + attractionForce.z
        )
      }

      // Mouse repulsion
      const repulsionForce = new CANNON.Vec3()
      repulsionForce.x = obj.body.position.x - mouseWorldPosition.x
      repulsionForce.y = obj.body.position.y - mouseWorldPosition.y
      repulsionForce.z = obj.body.position.z - mouseWorldPosition.z
      
      const mouseDistance = Math.sqrt(
        repulsionForce.x * repulsionForce.x +
        repulsionForce.y * repulsionForce.y +
        repulsionForce.z * repulsionForce.z
      )
      
      if (mouseDistance < 2.5 && mouseDistance > 0) { // Decreased range from 5 to 2.5
        const repulsionStrength = 25.0 / (mouseDistance * mouseDistance + 0.1) // Increased strength from 15.0 to 25.0
        repulsionForce.scale(repulsionStrength, repulsionForce)
        obj.body.force.set(
          obj.body.force.x + repulsionForce.x,
          obj.body.force.y + repulsionForce.y,
          obj.body.force.z + repulsionForce.z
        )
        
        // Add rotational torque from mouse interaction
        const torque = new CANNON.Vec3(
          (Math.random() - 0.5) * repulsionStrength * 0.1,
          (Math.random() - 0.5) * repulsionStrength * 0.1,
          (Math.random() - 0.5) * repulsionStrength * 0.1
        )
        obj.body.torque.set(
          obj.body.torque.x + torque.x,
          obj.body.torque.y + torque.y,
          obj.body.torque.z + torque.z
        )
      }

      // Apply damping
      obj.body.velocity.scale(0.99, obj.body.velocity)

      // Update mesh position to match physics body
      obj.mesh.position.copy(obj.body.position as any)
      obj.mesh.quaternion.copy(obj.body.quaternion as any)
    })
  }
}
