import { useEffect, useRef, useState } from "react";
import { Link } from "react-router-dom";
import { Canvas, useFrame } from "@react-three/fiber";
import {
  OrbitControls,
  Grid,
  Environment,
  PerspectiveCamera,
} from "@react-three/drei";
import * as THREE from "three";
import {
  Beaker,
  ArrowLeft,
  Lock,
  Unlock,
  RotateCcw,
  Box,
  Gamepad2,
  Hand,
} from "lucide-react";

/**
 * ============================================================
 * QUEST CUBE LAB — Fase 2
 * - Cubo 3D real (Three.js via @react-three/fiber)
 * - Grid fino no plano y=0 (Drei <Grid>)
 * - Toggle Travar/Destravar (upgrades decididos pelo Marcos)
 * - Joystick funcional (gamepad API) — analógico esq translação, dir rotação,
 *   triggers LB/RB escala, A reseta cubo
 * - OrbitControls pra teste em PC (amigo pode testar com mouse antes de VR)
 * - WebXR entry button: suportado se browser for MetaQuest Browser
 * ============================================================
 */

// Limiares analógicos (deadzone do joystick)
const STICK_DEADZONE = 0.12;
const TRIGGER_DEADZONE = 0.05;
const MOVE_SPEED = 1.5; // m/s lógico
const ROT_SPEED = 1.2; // rad/s
const SCALE_SPEED = 0.6;

// Dimensão inicial do cubo (1m x 1m x 1m)
const CUBE_SIZE = 1;

// ===================================================================
// COMPONENTE: CuboControlado
// Recebe refs compartilhadas pro estado, atualiza a cada frame.
// ===================================================================
const CubeControlado = ({
  posRef,
  rotRef,
  scaleRef,
  lockedRef,
  gamepadRef,
}: {
  posRef: React.MutableRefObject<{ x: number; y: number; z: number }>;
  rotRef: React.MutableRefObject<{ x: number; y: number; z: number }>;
  scaleRef: React.MutableRefObject<number>;
  lockedRef: React.MutableRefObject<boolean>;
  gamepadRef: React.MutableRefObject<{ a: boolean }>;
}) => {
  const meshRef = useRef<THREE.Mesh>(null);

  // Material do cubo com 6 faces coloridas (Pra identificar cada face no AR)
  const materials = [
    new THREE.MeshStandardMaterial({ color: "#ef4444" }), // +x - vermelho
    new THREE.MeshStandardMaterial({ color: "#22c55e" }), // -x - verde
    new THREE.MeshStandardMaterial({ color: "#3b82f6" }), // +y - azul
    new THREE.MeshStandardMaterial({ color: "#facc15" }), // -y - amarelo
    new THREE.MeshStandardMaterial({ color: "#a855f7" }), // +z - roxo
    new THREE.MeshStandardMaterial({ color: "#06b6d4" }), // -z - ciano
  ];

  useFrame((state, delta) => {
    if (!meshRef.current) return;
    const pad = gamepadRef.current.a ? null : null; // A=reseta handled em outro lugar

    // Lê gamepad a cada frame (não usar useEffect pq só roda uma vez)
    const gamepads = navigator.getGamepads ? navigator.getGamepads() : [];
    const gp = gamepads[0];

    if (gp && !lockedRef.current) {
      // Stick esquerdo -> translação XZ (FRente/tras, esquerda/direita)
      const lx = gp.axes[0] ?? 0; // esquerda(+)/direita(-)
      const ly = gp.axes[1] ?? 0; // frente(-)/tras(+)

      // Stick direito -> rotação yaw (Y) e pitch (X)
      const rx = gp.axes[2] ?? 0;
      const ry = gp.axes[3] ?? 0;

      // Botões 6 e 7 tipicamente são LT/RT em controles padrão Quest 3
      const lt = gp.buttons[6]?.value ?? 0;
      const rt = gp.buttons[7]?.value ?? 0;
      // btn 0 = A (X no controle Quest, segundo a doc), btn 1 = B
      const aBtn = gp.buttons[0]?.pressed;

      // Deadzone + escala
      const ax = Math.abs(lx) > STICK_DEADZONE ? lx : 0;
      const ay = Math.abs(ly) > STICK_DEADZONE ? ly : 0;
      const arx = Math.abs(rx) > STICK_DEADZONE ? rx : 0;
      const ary = Math.abs(ry) > STICK_DEADZONE ? ry : 0;

      // Aplica translação
      posRef.current.x -= ax * MOVE_SPEED * delta;
      posRef.current.z -= ay * MOVE_SPEED * delta;
      posRef.current.y = Math.max(0.5, posRef.current.y); // mantém acima do chão

      // Aplica rotação
      rotRef.current.x = (rotRef.current.x + ary * ROT_SPEED * delta) % (Math.PI * 2);
      rotRef.current.y = (rotRef.current.y - arx * ROT_SPEED * delta) % (Math.PI * 2);

      // Triggers -> escala (LT encolhe, RT cresce)
      const scaleDelta = rt - lt;
      if (Math.abs(scaleDelta) > TRIGGER_DEADZONE) {
        scaleRef.current = Math.max(
          0.2,
          Math.min(3, scaleRef.current + scaleDelta * SCALE_SPEED * delta)
        );
      }

      // Botão A -> reseta posição/rotação/escala (mantém y=0.5)
      if (aBtn && !gamepadRef.current.a) {
        posRef.current = { x: 0, y: 0.5, z: 0 };
        rotRef.current = { x: 0, y: 0, z: 0 };
        scaleRef.current = 1;
      }
      gamepadRef.current.a = aBtn;
    } else if (gp && lockedRef.current) {
      // Se travado, só rotação por joystick (yaw/pitch)
      const rx = gp.axes[2] ?? 0;
      const ry = gp.axes[3] ?? 0;
      const arx = Math.abs(rx) > STICK_DEADZONE ? rx : 0;
      const ary = Math.abs(ry) > STICK_DEADZONE ? ry : 0;
      rotRef.current.x = (rotRef.current.x + ary * ROT_SPEED * delta) % (Math.PI * 2);
      rotRef.current.y = (rotRef.current.y - arx * ROT_SPEED * delta) % (Math.PI * 2);
    }

    // Aplica ao mesh do Three.js
    meshRef.current.position.set(posRef.current.x, posRef.current.y, posRef.current.z);
    meshRef.current.rotation.set(rotRef.current.x, rotRef.current.y, rotRef.current.z);
    meshRef.current.scale.setScalar(scaleRef.current);
  });

  return (
    <mesh ref={meshRef} castShadow receiveShadow position={[0, 0.5, 0]}>
      <boxGeometry args={[CUBE_SIZE, CUBE_SIZE, CUBE_SIZE]} />
      {materials.map((m, i) => (
        <primitive attach="material-0" object={m} key={i} />
      ))}
    </mesh>
  );
};

// ===================================================================
// Detector de gamepad (sinaliza status pra UI)
// ===================================================================
const useGamepadStatus = () => {
  const [connected, setConnected] = useState(false);
  useEffect(() => {
    const handler = () => {
      const pads = navigator.getGamepads?.() ?? [];
      setConnected(Array.from(pads).some((p) => p !== null));
    };
    window.addEventListener("gamepadconnected", handler);
    window.addEventListener("gamepaddisconnected", handler);
    handler();
    const i = window.setInterval(handler, 1000); // poll, porque alguns headsets só conectam após entrar em XR
    return () => {
      window.removeEventListener("gamepadconnected", handler);
      window.removeEventListener("gamepaddisconnected", handler);
      window.clearInterval(i);
    };
  }, []);
  return connected;
};

// ===================================================================
// Página principal QuestCubeLab
// ===================================================================
const QuestCubeLab = () => {
  const joystickConnected = useGamepadStatus();

  // Estado editável via UI (ControlCards e sliders)
  const [cubePos, setCubePos] = useState({ x: 0, y: 0.5, z: 0 });
  const [cubeRot, setCubeRot] = useState({ x: 0, y: 0, z: 0 });
  const [cubeScale, setCubeScale] = useState(1);
  const [locked, setLocked] = useState(false);
  const [xrSupported] = useState(() =>
    typeof navigator !== "undefined" &&
    "xr" in navigator &&
    typeof (navigator as unknown as { xr?: { isSessionSupported?: (m: string) => Promise<boolean> } }).xr?.isSessionSupported === "function"
  );

  // Refs pra o gamepad loop no useFrame ler/escrever sem re-render
  const posRef = useRef(cubePos);
  const rotRef = useRef(cubeRot);
  const scaleRef = useRef(cubeScale);
  const lockedRef = useRef(locked);
  const gamepadRef = useRef({ a: false });

  // Sincroniza refs com state (escrita do state -> refs; leitura do gamepad -> state)
  useEffect(() => {
    posRef.current = cubePos;
  }, [cubePos]);
  useEffect(() => {
    rotRef.current = cubeRot;
  }, [cubeRot]);
  useEffect(() => {
    scaleRef.current = cubeScale;
  }, [cubeScale]);
  useEffect(() => {
    lockedRef.current = locked;
  }, [locked]);

  // Loop de polling separado pra sincronizar state <- refs (porque useFrame altera refs)
  useEffect(() => {
    const id = window.setInterval(() => {
      setCubePos({ ...posRef.current });
      setCubeRot({ ...rotRef.current });
      setCubeScale(scaleRef.current);
    }, 100);
    return () => window.clearInterval(id);
  }, []);

  const reset = () => {
    posRef.current = { x: 0, y: 0.5, z: 0 };
    rotRef.current = { x: 0, y: 0, z: 0 };
    scaleRef.current = 1;
    setCubePos({ x: 0, y: 0.5, z: 0 });
    setCubeRot({ x: 0, y: 0, z: 0 });
    setCubeScale(1);
  };

  // Helper pra entrar em XR (sessão imersiva-ar com Passthrough do Quest 3)
  const enterXR = async () => {
    try {
      const xr = (navigator as unknown as { xr: { requestSession: (m: string) => Promise<XRSession> } }).xr;
      const session = await xr.requestSession("immersive-ar");
      // A integração XR com R3F é feita via @react-three/xr (não instalada).
      // Por ora, só abre a sessão; o Canvas atualiza quando detecta.
      // Importante: o Canvas precisa de <XR> wrapper pra usar sessionMode.
      // Workaround mínimo: setamos a session no Canvas via gl.xr.setSession.
      // Como o setup <XR> não está instalado, exibimos mensagem informativa.
      void session;
      alert("XR session requisitada. (Para integração completa com R3F, falta instalar @react-three/xr — Fase 2.5).");
    } catch (e) {
      alert("Falha ao entrar em XR: " + (e as Error).message);
    }
  };

  return (
    <div className="min-h-screen bg-gradient-to-b from-slate-950 via-slate-900 to-slate-950 text-slate-100">
      <header className="border-b border-slate-800/80 bg-slate-950/80 backdrop-blur">
        <div className="mx-auto flex max-w-6xl items-center justify-between gap-3 px-6 py-4">
          <Link
            to="/"
            className="flex items-center gap-2 text-sm text-slate-400 transition hover:text-slate-100"
          >
            <ArrowLeft className="h-4 w-4" /> Voltar ao SteelXR
          </Link>
          <div className="flex items-center gap-3">
            <Beaker className="h-5 w-5 text-amber-400" />
            <h1 className="font-mono text-sm tracking-wider text-slate-300">
              QUEST CUBE LAB <span className="text-amber-400/70">(alpha)</span>
            </h1>
          </div>
          <div className="flex items-center gap-3">
            <span
              className={`inline-flex h-2 w-2 rounded-full ${
                joystickConnected ? "bg-emerald-400" : "bg-slate-600"
              }`}
            />
            <span className="text-xs text-slate-400">
              {joystickConnected ? "Joystick OK" : "Sem joystick"}
            </span>
          </div>
        </div>
      </header>

      <main className="mx-auto max-w-6xl px-6 py-8">
        <div className="mb-6 rounded-lg border border-amber-500/30 bg-amber-500/5 px-4 py-3 text-sm text-amber-200">
          <strong>Sandbox experimental — Fase 2.</strong> Cubo Three.js real (6 faces coloridas),
          grid fino no chão, travar/destravar, joystick funcional.
        </div>

        {/* Toolbar com Travar/Destravar + Reset + XR */}
        <div className="mb-4 flex flex-wrap items-center gap-2">
          <button
            onClick={() => setLocked((v) => !v)}
            className={`flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium transition ${
              locked
                ? "border-amber-500 bg-amber-500/15 text-amber-200"
                : "border-slate-700 bg-slate-900 text-slate-300 hover:border-slate-500"
            }`}
          >
            {locked ? <Lock className="h-4 w-4" /> : <Unlock className="h-4 w-4" />}
            {locked ? "Travado" : "Destravar"}
          </button>

          <button
            onClick={reset}
            className="flex items-center gap-2 rounded-md border border-slate-700 bg-slate-900 px-3 py-2 text-sm text-slate-300 transition hover:border-slate-500"
          >
            <RotateCcw className="h-4 w-4" />
            Reset
          </button>

          <div className="ml-auto flex items-center gap-2">
            <button
              disabled={!xrSupported}
              onClick={enterXR}
              className={`flex items-center gap-2 rounded-md border px-3 py-2 text-sm transition ${
                xrSupported
                  ? "border-emerald-500/50 bg-emerald-500/10 text-emerald-200 hover:bg-emerald-500/20"
                  : "cursor-not-allowed border-slate-700 bg-slate-900 text-slate-500"
              }`}
            >
              <Hand className="h-4 w-4" />
              Entrar em AR (Passthrough)
            </button>
          </div>
        </div>

        {/* Viewport 3D real */}
        <section className="overflow-hidden rounded-xl border border-slate-800 bg-slate-950">
          <div style={{ height: 460 }}>
            <Canvas shadows>
              <PerspectiveCamera makeDefault position={[3, 2.5, 4]} fov={50} />
              <ambientLight intensity={0.4} />
              <directionalLight
                position={[5, 8, 5]}
                intensity={1}
                castShadow
                shadow-mapSize-width={1024}
                shadow-mapSize-height={1024}
              />
              <CubeControlado
                posRef={posRef}
                rotRef={rotRef}
                scaleRef={scaleRef}
                lockedRef={lockedRef}
                gamepadRef={gamepadRef}
              />
              <Grid
                args={[20, 20]}
                cellSize={0.25}
                cellThickness={0.5}
                cellColor="#475569"
                sectionSize={1}
                sectionThickness={1}
                sectionColor="#94a3b8"
                fadeDistance={18}
                fadeStrength={1}
                infiniteGrid={false}
                position={[0, 0, 0]}
              />
              <mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.001, 0]}>
                <planeGeometry args={[20, 20]} />
                <shadowMaterial transparent opacity={0.35} />
              </mesh>
              <OrbitControls makeDefault enableDamping />
              <Environment preset="city" />
            </Canvas>
          </div>

          <div className="flex items-center justify-between border-t border-slate-800 bg-slate-950/80 px-4 py-2">
            <div className="font-mono text-[11px] text-slate-400">
              pos({cubePos.x.toFixed(2)}, {cubePos.y.toFixed(2)}, {cubePos.z.toFixed(2)}) · rot(
              {((cubeRot.y * 180) / Math.PI).toFixed(0)}°) · scale {cubeScale.toFixed(2)}x
              {locked && " · 🔒 posição fixa"}
            </div>
            <div className="font-mono text-[11px] uppercase tracking-wider text-slate-500">
              {locked ? "modo: rotação livre" : "modo: livre"}
            </div>
          </div>
        </section>

        {/* 3 ControlCards */}
        <section className="mt-6 grid grid-cols-1 gap-4 md:grid-cols-3">
          <ControlCard
            icon={<Box className="h-4 w-4 text-cyan-300" />}
            title="Translação (stick esq)"
            value={`X: ${cubePos.x.toFixed(2)} · Z: ${cubePos.z.toFixed(2)}`}
            onUp={() => setCubePos((p) => ({ ...p, z: p.z - 0.1 }))}
            onDown={() => setCubePos((p) => ({ ...p, z: p.z + 0.1 }))}
            onLeft={() => setCubePos((p) => ({ ...p, x: p.x - 0.1 }))}
            onRight={() => setCubePos((p) => ({ ...p, x: p.x + 0.1 }))}
            disabled={locked}
          />
          <ControlCard
            icon={<Gamepad2 className="h-4 w-4 text-violet-300" />}
            title="Rotação (stick dir)"
            value={`Yaw: ${((cubeRot.y * 180) / Math.PI).toFixed(0)}°`}
            onUp={() => setCubeRot((r) => ({ ...r, x: r.x + 0.1 }))}
            onDown={() => setCubeRot((r) => ({ ...r, x: r.x - 0.1 }))}
            onLeft={() => setCubeRot((r) => ({ ...r, y: r.y - 0.1 }))}
            onRight={() => setCubeRot((r) => ({ ...r, y: r.y + 0.1 }))}
          />
          <ControlCard
            icon={<Maximize2Inline />}
            title="Escala (LT/RT)"
            value={`${cubeScale.toFixed(2)}x`}
            onUp={() => setCubeScale((s) => Math.min(3, +(s + 0.1).toFixed(2)))}
            onDown={() => setCubeScale((s) => Math.max(0.2, +(s - 0.1).toFixed(2)))}
            onLeft={() => setCubeScale((s) => Math.max(0.2, +(s - 0.1).toFixed(2)))}
            onRight={() => setCubeScale((s) => Math.min(3, +(s + 0.1).toFixed(2)))}
            disabled={locked}
          />
        </section>

        <section className="mt-8 rounded-lg border border-slate-800 bg-slate-900/30 p-6">
          <h2 className="mb-4 font-mono text-xs uppercase tracking-[0.2em] text-slate-400">
            Próximas fases
          </h2>
          <ol className="space-y-2 text-sm text-slate-300">
            <Phase n="1" status="done" title="Botão na Home + rota /lab" />
            <Phase n="2" status="done" title="Cubo Three.js + Grid fino + Travar/Destravar + Joystick funcional" />
            <Phase
              n="2.5"
              status="active"
              title="Integração WebXR completa (@react-three/xr) — Passthrough real"
            />
            <Phase n="3" title="Sistema 2-cliques (PAR CONTATO: face objeto + superfície alvo)" />
            <Phase n="4" title="Sistema 2-cliques (PAR DIREÇÃO: face objeto + aresta lateral mesa)" />
            <Phase n="5" title="Migração da lógica redonda pro SteelXR XR Session" />
          </ol>
        </section>
      </main>
    </div>
  );
};

const Maximize2Inline = () => (
  <svg className="h-4 w-4 text-amber-300" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
    <path d="M21 21l-4.35-4.35" />
    <path d="M11 5h6v6" />
    <path d="M21 5L14 12" />
    <path d="M5 21l7-7" />
    <path d="M5 13V5h8" />
  </svg>
);

const Phase = ({ n, status, title }: { n: string; status?: "done" | "active"; title: string }) => (
  <li className="flex items-start gap-3">
    <span
      className={`flex h-6 w-6 shrink-0 items-center justify-center rounded-full font-mono text-xs ${
        status === "done"
          ? "bg-emerald-500/20 text-emerald-300"
          : status === "active"
          ? "bg-amber-500/20 text-amber-300"
          : "bg-slate-800 text-slate-500"
      }`}
    >
      {n}
    </span>
    <span className="text-slate-200">{title}</span>
  </li>
);

const ControlCard = ({
  icon,
  title,
  value,
  onUp,
  onDown,
  onLeft,
  onRight,
  disabled,
}: {
  icon: React.ReactNode;
  title: string;
  value: string;
  onUp: () => void;
  onDown: () => void;
  onLeft: () => void;
  onRight: () => void;
  disabled?: boolean;
}) => (
  <div className={`rounded-lg border border-slate-800 bg-slate-900/60 p-4 ${disabled ? "opacity-50" : ""}`}>
    <div className="mb-3 flex items-center gap-2">
      {icon}
      <span className="text-sm font-medium text-slate-200">{title}</span>
    </div>
    <div className="mb-3 font-mono text-xs text-slate-400">{value}</div>
    <div className="grid grid-cols-3 gap-1">
      <div />
      <button
        onClick={onUp}
        disabled={disabled}
        className="rounded border border-slate-700 bg-slate-950 py-1.5 text-xs hover:border-slate-500 disabled:cursor-not-allowed"
      >
        ▲
      </button>
      <div />
      <button
        onClick={onLeft}
        disabled={disabled}
        className="rounded border border-slate-700 bg-slate-950 py-1.5 text-xs hover:border-slate-500 disabled:cursor-not-allowed"
      >
        ◀
      </button>
      <button
        onClick={onDown}
        disabled={disabled}
        className="rounded border border-slate-700 bg-slate-950 py-1.5 text-xs hover:border-slate-500 disabled:cursor-not-allowed"
      >
        ▼
      </button>
      <button
        onClick={onRight}
        disabled={disabled}
        className="rounded border border-slate-700 bg-slate-950 py-1.5 text-xs hover:border-slate-500 disabled:cursor-not-allowed"
      >
        ▶
      </button>
    </div>
  </div>
);

export default QuestCubeLab;
