// world/flycam.js (Lane A) — `?fly=1` noclip inspection camera.
// Owed to the other lanes per LANE_A_WORLD.md: a way to look at the canal without Lane B's
// player existing. True noclip (free 6DOF, ignores world.collide) — it is a debug tool, not
// a preview of arena-mode flight; Lane B owns how the ship actually feels.
//
// Not wired into boot.js yet: boot owns the camera and `?fly=1` currently drives a rail cam.
// The exact patch is offered in LANE_A_NOTES.md §-> Lane F.
//
//   W/S forward/back · A/D strafe · Q/E down/up · Shift boost · drag to look · R reset to start

import * as THREE from 'three';

export function createFlyCam({ camera, dom = window, world, speed = 35 }) {
  const keys = new Set();
  let yaw = 0, pitch = 0, dragging = false;

  function reset() {
    const f = world.sample(4);
    camera.position.copy(f.pos).addScaledVector(f.tan, -6);
    yaw = Math.atan2(-f.tan.x, -f.tan.z);
    pitch = Math.asin(THREE.MathUtils.clamp(f.tan.y, -1, 1));
  }

  const onDown = (e) => { keys.add(e.code); if (e.code === 'KeyR') reset(); };
  const onUp = (e) => keys.delete(e.code);
  const onBlur = () => keys.clear();
  const onMouseDown = () => { dragging = true; };
  const onMouseUp = () => { dragging = false; };
  const onMouseMove = (e) => {
    if (!dragging) return;
    yaw -= e.movementX * 0.003;
    pitch = THREE.MathUtils.clamp(pitch - e.movementY * 0.003, -1.5, 1.5);
  };

  addEventListener('keydown', onDown);
  addEventListener('keyup', onUp);
  addEventListener('blur', onBlur);
  dom.addEventListener('mousedown', onMouseDown);
  addEventListener('mouseup', onMouseUp);
  addEventListener('mousemove', onMouseMove);
  reset();

  const fwd = new THREE.Vector3(), right = new THREE.Vector3(), up = new THREE.Vector3(0, 1, 0);

  return {
    get position() { return camera.position; },
    reset,
    update(dt) {
      camera.up.copy(up);                       // noclip stays world-up: no frame roll to fight
      camera.rotation.set(pitch, yaw, 0, 'YXZ');
      fwd.set(0, 0, -1).applyEuler(camera.rotation);
      right.set(1, 0, 0).applyEuler(camera.rotation);
      const v = speed * (keys.has('ShiftLeft') || keys.has('ShiftRight') ? 3 : 1) * dt;
      if (keys.has('KeyW')) camera.position.addScaledVector(fwd, v);
      if (keys.has('KeyS')) camera.position.addScaledVector(fwd, -v);
      if (keys.has('KeyD')) camera.position.addScaledVector(right, v);
      if (keys.has('KeyA')) camera.position.addScaledVector(right, -v);
      if (keys.has('KeyE')) camera.position.addScaledVector(up, v);
      if (keys.has('KeyQ')) camera.position.addScaledVector(up, -v);
    },
    dispose() {
      removeEventListener('keydown', onDown);
      removeEventListener('keyup', onUp);
      removeEventListener('blur', onBlur);
      dom.removeEventListener('mousedown', onMouseDown);
      removeEventListener('mouseup', onMouseUp);
      removeEventListener('mousemove', onMouseMove);
    },
  };
}
