import { useEffect, useRef } from 'react';
import { useFrame, useThree } from '@react-three/fiber';
import { PointerLockControls } from '@react-three/drei';
import * as THREE from 'three';
import { useModelStore } from '@/stores/useModelStore';

export function DesktopFirstPersonControls() {
  const { camera } = useThree();
  const activeMode = useModelStore((s) => s.desktopCameraMode);
  const xrEnvironment = useModelStore((s) => s.xrEnvironment);

  // Armazena o estado atual das teclas de locomoção
  const keys = useRef({
    w: false,
    a: false,
    s: false,
    d: false,
    arrowup: false,
    arrowleft: false,
    arrowdown: false,
    arrowright: false,
    q: false, // voar para baixo
    e: false, // voar para cima
  });

  useEffect(() => {
    if (activeMode !== 'walk') return;

    const handleKeyDown = (e: KeyboardEvent) => {
      const k = e.key.toLowerCase();
      if (k in keys.current) {
        keys.current[k as keyof typeof keys.current] = true;
      }
    };

    const handleKeyUp = (e: KeyboardEvent) => {
      const k = e.key.toLowerCase();
      if (k in keys.current) {
        keys.current[k as keyof typeof keys.current] = false;
      }
    };

    window.addEventListener('keydown', handleKeyDown);
    window.addEventListener('keyup', handleKeyUp);
    
    return () => {
      window.removeEventListener('keydown', handleKeyDown);
      window.removeEventListener('keyup', handleKeyUp);
    };
  }, [activeMode]);

  // Define posições iniciais amigáveis ao alternar para o modo passeio
  const lastMode = useRef<string | null>(null);
  useEffect(() => {
    if (activeMode === 'walk' && lastMode.current !== 'walk') {
      if (xrEnvironment === 'office') {
        // Posiciona o operador em pé na ponta da mesa
        camera.position.set(0, 1.4, 1.3);
        camera.lookAt(0, 0.85, 0);
      } else {
        // Posiciona no campo aberto em escala real
        camera.position.set(0, 1.65, 3);
        camera.lookAt(0, 1.0, 0);
      }
    }
    lastMode.current = activeMode;
  }, [activeMode, xrEnvironment, camera]);

  useFrame((state, delta) => {
    if (activeMode !== 'walk') return;

    const speed = 2.0 * delta; // Metros por frame adaptativo
    const rotSpeed = 1.5 * delta;

    const direction = new THREE.Vector3();
    const side = new THREE.Vector3();

    // Obtém vetor de olhar da câmera
    camera.getWorldDirection(direction);
    direction.y = 0; // Trava o vetor na horizontal para não voar para cima/baixo ao olhar
    direction.normalize();

    // Obtém vetor lateral
    side.crossVectors(camera.up, direction).normalize();

    // 1. Leituras do teclado
    let moveFwd = 0;
    let moveSide = 0;
    let moveUp = 0;

    if (keys.current.w || keys.current.arrowup) moveFwd += 1;
    if (keys.current.s || keys.current.arrowdown) moveFwd -= 1;
    if (keys.current.d || keys.current.arrowright) moveSide -= 1;
    if (keys.current.a || keys.current.arrowleft) moveSide += 1;
    if (keys.current.e) moveUp += 1;
    if (keys.current.q) moveUp -= 1;

    camera.position.addScaledVector(direction, moveFwd * speed);
    camera.position.addScaledVector(side, moveSide * speed);
    camera.position.y += moveUp * speed;

    // 2. Leituras da Gamepad API (Xbox / PlayStation)
    const gamepads = navigator.getGamepads();
    const gp = gamepads[0] || gamepads[1];
    if (gp) {
      const deadzone = 0.15;

      // Analógico Esquerdo (Locomoção)
      const stickLX = gp.axes[0]; // Eixo lateral
      const stickLY = gp.axes[1]; // Eixo frente/trás

      if (Math.abs(stickLY) > deadzone) {
        camera.position.addScaledVector(direction, -stickLY * speed);
      }
      if (Math.abs(stickLX) > deadzone) {
        camera.position.addScaledVector(side, -stickLX * speed);
      }

      // Analógico Direito (Rotação da Câmera)
      const stickRX = gp.axes[2]; // Rotação Y
      const stickRY = gp.axes[3]; // Olhar X cima/baixo

      if (Math.abs(stickRX) > deadzone) {
        camera.rotation.y -= stickRX * rotSpeed * 1.6;
      }
      if (Math.abs(stickRY) > deadzone) {
        // Rotaciona verticalmente
        camera.rotation.x -= stickRY * rotSpeed * 1.6;
        // Limita ângulo vertical para evitar inverter a visão (entre -80° e 80°)
        camera.rotation.x = Math.max(-1.4, Math.min(1.4, camera.rotation.x));
      }

      // Gatilhos para controle de altura (RT sobe, LT desce)
      const triggerLT = gp.buttons[6];
      const triggerRT = gp.buttons[7];
      if (triggerRT && triggerRT.value > 0.1) {
        camera.position.y += triggerRT.value * speed;
      }
      if (triggerLT && triggerLT.value > 0.1) {
        camera.position.y -= triggerLT.value * speed;
      }
    }

    // Trava de colisão com o chão/mesa para manter realismo
    const minHeight = xrEnvironment === 'office' ? 0.9 : 0.1;
    if (camera.position.y < minHeight) {
      camera.position.y = minHeight;
    }
  });

  if (activeMode !== 'walk') return null;

  return <PointerLockControls makeDefault />;
}
