/**
 * DEVKIT — Visual fake controllers + keyboard driver.
 *
 * Renders two spheres (L=blue, R=red) at the fake controller positions and
 * listens to global keyboard for grip/trigger/movement. Mounted only when
 * SimXR is active.
 *
 * Keys:
 *   Q / W       → hold grip Left / Right (analog = 1.0)
 *   A / S       → hold trigger Left / Right (analog = 1.0)
 *   1 / 2       → select Left / Right as the active hand
 *   Arrows      → move active hand on X (←→) / Y (↑↓)
 *   Shift+Arrows→ move active hand on Z (↑=forward, ↓=back)
 *   R           → reset hand poses
 */
import { useEffect, useRef, useState } from 'react';
import { useFrame } from '@react-three/fiber';
import * as THREE from 'three';
import { fakeInput, setFakeActive } from './fakeInputStore';

const STEP = 0.03; // m per keypress

export function FakeControllers() {
  const leftMesh = useRef<THREE.Mesh>(null);
  const rightMesh = useRef<THREE.Mesh>(null);
  const [, force] = useState(0);
  const activeHand = useRef<'left' | 'right'>('right');

  useEffect(() => {
    setFakeActive(true);
    return () => setFakeActive(false);
  }, []);

  useEffect(() => {
    const keys = new Set<string>();

    const apply = () => {
      const pos = new THREE.Vector3();
      const quat = new THREE.Quaternion();
      const scl = new THREE.Vector3();
      const hand = fakeInput[activeHand.current];
      hand.gripWorld.decompose(pos, quat, scl);

      const dx = (keys.has('ArrowRight') ? STEP : 0) - (keys.has('ArrowLeft') ? STEP : 0);
      const dyOrZ = (keys.has('ArrowUp') ? STEP : 0) - (keys.has('ArrowDown') ? STEP : 0);
      const shift = keys.has('Shift');
      pos.x += dx;
      if (shift) pos.z -= dyOrZ; // up = forward (-Z)
      else pos.y += dyOrZ;

      hand.gripWorld.compose(pos, quat, scl);

      // grip / trigger
      fakeInput.left.gripValue = keys.has('q') ? 1 : 0;
      fakeInput.right.gripValue = keys.has('w') ? 1 : 0;
      fakeInput.left.triggerValue = keys.has('a') ? 1 : 0;
      fakeInput.right.triggerValue = keys.has('s') ? 1 : 0;

      force((n) => n + 1);
    };

    const onDown = (e: KeyboardEvent) => {
      const k = e.key === 'Shift' ? 'Shift' : e.key;
      keys.add(k);
      if (k === '1') activeHand.current = 'left';
      else if (k === '2') activeHand.current = 'right';
      else if (k === 'r' || k === 'R') {
        fakeInput.left.gripWorld.makeTranslation(-0.25, 1.2, -0.5);
        fakeInput.right.gripWorld.makeTranslation(0.25, 1.2, -0.5);
        force((n) => n + 1);
        return;
      }
      apply();
    };
    const onUp = (e: KeyboardEvent) => {
      const k = e.key === 'Shift' ? 'Shift' : e.key;
      keys.delete(k);
      apply();
    };

    window.addEventListener('keydown', onDown);
    window.addEventListener('keyup', onUp);
    return () => {
      window.removeEventListener('keydown', onDown);
      window.removeEventListener('keyup', onUp);
    };
  }, []);

  // Sync mesh visuals to fake state each frame
  useFrame(() => {
    if (leftMesh.current) {
      const p = new THREE.Vector3().setFromMatrixPosition(fakeInput.left.gripWorld);
      leftMesh.current.position.copy(p);
      const grabbing = fakeInput.left.gripValue > 0.7;
      const mat = leftMesh.current.material as THREE.MeshStandardMaterial;
      mat.emissiveIntensity = grabbing ? 1.5 : 0.4;
    }
    if (rightMesh.current) {
      const p = new THREE.Vector3().setFromMatrixPosition(fakeInput.right.gripWorld);
      rightMesh.current.position.copy(p);
      const grabbing = fakeInput.right.gripValue > 0.7;
      const mat = rightMesh.current.material as THREE.MeshStandardMaterial;
      mat.emissiveIntensity = grabbing ? 1.5 : 0.4;
    }
  });

  return (
    <>
      <mesh ref={leftMesh}>
        <sphereGeometry args={[0.04, 16, 16]} />
        <meshStandardMaterial color="#3b82f6" emissive="#3b82f6" emissiveIntensity={0.4} />
      </mesh>
      <mesh ref={rightMesh}>
        <sphereGeometry args={[0.04, 16, 16]} />
        <meshStandardMaterial color="#ef4444" emissive="#ef4444" emissiveIntensity={0.4} />
      </mesh>
    </>
  );
}
