import { useEffect, useRef, useMemo, useCallback, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { useGLTF, Grid, Html, Line, OrbitControls, Text } from '@react-three/drei';
import { XR, useXR, XROrigin, useXRHitTest } from '@react-three/xr';
import { xrStore as store } from '@/stores/useXRStore';
import * as THREE from 'three';
import { useModelStore } from '@/stores/useModelStore';
import { toast } from 'sonner';
import { ArrowLeft, Download, QrCode, Crosshair, Home, Glasses, Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { generateMarkerDownloadURL } from '@/lib/trackingMarker';
import { XRHud } from '@/components/XRHud';
import { ShareButton } from '@/components/ShareButton';
import { XRHudInWorld } from '@/components/three/XRHudInWorld';
import { XRBroadcastMirror } from '@/components/three/XRBroadcastMirror';
import { findNearestVertex } from '@/components/three/SmartMeasure';
import { XRHitTestPlacement } from '@/components/three/XRHitTestPlacement';
import { XRGrabbable } from '@/components/three/XRGrabbable';
import { XRControllerMeasure } from '@/components/three/XRControllerMeasure';
import { ControllerLocomotion } from '@/components/three/ControllerLocomotion';
// DEVKIT: remove these imports + all `// DEVKIT:` blocks below to strip devkit
import { useDevKit } from '@/devkit/useDevKit';
import { DevPanel } from '@/devkit/DevPanel';
import { FakeControllers } from '@/devkit/FakeControllers';
import { VisibilityApplier, findElementRoot, getColorForMaterialName } from '@/components/three/ModelViewer';
import { registerModelLocalGroup, unregisterModelLocalGroup } from '@/lib/modelTransforms';
import { parseIFCtoThree } from '@/lib/convertIFC';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import {
  xrCalibration,
  pushXRModelFaceNormal,
  computeXRCalibrationQuaternion,
  subscribeXRCalibration,
  pushXRRealPoint,
  pushXRVirtualPoint,
  computeVirtRealTransform,
  activeModelGroupRef,
} from '@/components/three/xrCalibrationBus';

// --- Diagnóstico XR ---
console.log('[XR] Inicializando store...');
if (navigator.xr) {
  navigator.xr.isSessionSupported('immersive-ar').then((supported) => {
    console.log('[XR] immersive-ar suportado:', supported);
  });
}

// `store` is now imported from `@/stores/useXRStore`

// ─── XRModel ───────────────────────────────────────────
function XRModel({ sceneModel }: { sceneModel: import('@/stores/useModelStore').SceneModel }) {
  const [rawScene, setRawScene] = useState<THREE.Object3D | null>(null);
  const scene = useMemo(() => rawScene ? rawScene.clone(true) : null, [rawScene]);

  useEffect(() => {
    let active = true;
    const isIfc = sceneModel.fileName.toLowerCase().endsWith('.ifc');
    if (isIfc) {
      fetch(sceneModel.url)
        .then((res) => res.arrayBuffer())
        .then((buf) => parseIFCtoThree(buf))
        .then((threeScene) => {
          if (active) setRawScene(threeScene);
        })
        .catch((err) => console.error('[XRModel] IFC parsing error', err));
    } else {
      const loader = new GLTFLoader();
      loader.load(
        sceneModel.url,
        (gltf) => {
          if (active) setRawScene(gltf.scene);
        },
        undefined,
        (err) => console.error('[XRModel] GLTF loading error', err)
      );
    }
    return () => {
      active = false;
    };
  }, [sceneModel.url, sceneModel.fileName]);

  const ref = useRef<THREE.Group>(null);
  const calGroupRef = useRef<THREE.Group>(null);
  const localFrameRef = useRef<THREE.Group>(null);
  const topGroupRef = useRef<THREE.Group>(null);

  // Escuta mudanças de calibração para re-renderizar no AR
  const [, setCalTick] = useState(0);
  useEffect(() => subscribeXRCalibration(() => setCalTick(t => t + 1)), []);

  useEffect(() => {
    const g = localFrameRef.current;
    if (!g) return;
    registerModelLocalGroup(sceneModel.id, g);
    return () => unregisterModelLocalGroup(sceneModel.id, g);
  }, [sceneModel.id]);

  const fineTuning = sceneModel.fineTuning;
  const opacity = useModelStore((s) => s.opacity);
  const renderMode = useModelStore((s) => s.renderMode);
  const wireframeColor = useModelStore((s) => s.wireframeColor);
  const wireframeThickness = useModelStore((s) => s.wireframeThickness);
  const edgeThresholdAngle = useModelStore((s) => s.edgeThresholdAngle);
  const checklist = useModelStore((s) => s.checklist);
  const measureMode = useModelStore((s) => s.measureMode);
  const ifcColorMode = useModelStore((s) => s.ifcColorMode);

  const modelInfo = useMemo(() => {
    if (!scene) return { size: new THREE.Vector3(), center: new THREE.Vector3() };
    const box = new THREE.Box3().setFromObject(scene);
    const size = new THREE.Vector3();
    const center = new THREE.Vector3();
    box.getSize(size);
    box.getCenter(center);
    return { size, center };
  }, [scene]);

  useEffect(() => {
    if (!scene) return;
    const hasRejected = checklist.some(i => i.status === 'rejected');
    const allApproved = checklist.every(i => i.status === 'approved');

    scene.traverse((child) => {
      if (child instanceof THREE.Mesh) {
        if (Array.isArray(child.material)) {
          child.material = child.material.map(m => m.clone());
        } else {
          child.material = child.material.clone();
        }

        const toRemove: THREE.Object3D[] = [];
        child.children.forEach(c => {
          if (c.userData.__edgeLine) toRemove.push(c);
        });
        toRemove.forEach(c => {
          if (c instanceof THREE.LineSegments) {
            c.geometry.dispose();
            (c.material as THREE.Material).dispose();
          }
          child.remove(c);
        });

        const materials = Array.isArray(child.material) ? child.material : [child.material];
        materials.forEach((mat: THREE.Material) => {
          if (mat instanceof THREE.MeshStandardMaterial) {
            if (renderMode === 'edges' && !measureMode) {
              mat.visible = false;
            } else {
              mat.visible = true;
              const targetOpacity = measureMode ? 0.25 : opacity;
              mat.transparent = targetOpacity < 1;
              mat.opacity = targetOpacity;
              mat.wireframe = renderMode === 'wireframe';
              if (renderMode === 'wireframe') {
                mat.wireframeLinewidth = wireframeThickness;
                mat.color.set(wireframeColor);
              } else if (hasRejected) {
                mat.color.setHSL(0, 0.7, 0.5);
              } else if (allApproved) {
                mat.color.setHSL(0.38, 0.7, 0.45);
              } else {
                const root = findElementRoot(child);
                const matName = root?.userData?.materialName;
                const descName = root?.userData?.properties?.description || root?.userData?.description;
                if (ifcColorMode === 'material' && matName) {
                  mat.color.set(getColorForMaterialName(matName));
                } else if (ifcColorMode === 'description' && descName) {
                  mat.color.set(getColorForMaterialName(descName));
                } else {
                  mat.color.set(sceneModel.color);
                }
              }
            }
            mat.needsUpdate = true;
          }
        });

        if ((renderMode === 'edges' || measureMode) && child.geometry) {
          const edgesGeo = new THREE.EdgesGeometry(child.geometry, edgeThresholdAngle);
          const lineMat = new THREE.LineBasicMaterial({
            color: measureMode ? '#00f3ff' : wireframeColor,
            linewidth: measureMode ? 2 : wireframeThickness,
            toneMapped: false,
            transparent: true,
            opacity: 0.95,
          });
          const lineSegments = new THREE.LineSegments(edgesGeo, lineMat);
          lineSegments.userData.__edgeLine = true;
          child.add(lineSegments);
        }
      }
    });
  }, [scene, opacity, renderMode, checklist, wireframeColor, wireframeThickness, edgeThresholdAngle, sceneModel.color, measureMode, ifcColorMode]);

  const rotXRad = (fineTuning.rotX * Math.PI) / 180;
  const rotYRad = (fineTuning.rotY * Math.PI) / 180;
  const rotZRad = (fineTuning.rotZ * Math.PI) / 180;
  const s = fineTuning.scale ?? 1;
  const scaleRatio = useModelStore((st) => st.scaleRatio);
  const renderFactor = scaleRatio?.factor ?? 1;

  const rotationEuler = useMemo(() => {
    return new THREE.Euler(rotXRad, rotYRad, rotZRad, 'YXZ');
  }, [rotXRad, rotYRad, rotZRad]);

  const calQuatArr = sceneModel.calibrationQuat;
  const isCalibratingThis = xrCalibration.modelId === sceneModel.id && xrCalibration.step !== 'idle' && xrCalibration.step !== 'done';
  const calQuat = useMemo(() => {
    if (isCalibratingThis) return new THREE.Quaternion();
    if (!calQuatArr) return new THREE.Quaternion();
    return new THREE.Quaternion(calQuatArr[0], calQuatArr[1], calQuatArr[2], calQuatArr[3]);
  }, [calQuatArr, isCalibratingThis]);

  if (!sceneModel.visible) return null;
  if (!scene) return null;

  return (
    <group
      ref={topGroupRef}
      scale={[renderFactor, renderFactor, renderFactor]}
      onClick={(e) => {
        e.stopPropagation();

        // Calibração do Grid em AR (clonando os mesmos princípios do modo viewer)
        const gridCalibMode = useModelStore.getState().gridCalibMode;
        if (gridCalibMode && e.point) {
          useModelStore.setState({
            gridY: e.point.y - 0.001,
            gridAutoFollow: false,
            gridCalibMode: false,
            showGrid: true,
          });
          return;
        }

        // Calibração XR da Peça: captura normal da face do modelo em espaço de mundo.
        if (
          xrCalibration.modelId === sceneModel.id &&
          xrCalibration.alignType === 'cube' &&
          (xrCalibration.step === 'await-model-1' || xrCalibration.step === 'await-model-2' || xrCalibration.step === 'await-model-3') &&
          e.face && e.object
        ) {
          const n = e.face.normal.clone();
          const nm = new THREE.Matrix3().getNormalMatrix(e.object.matrixWorld);
          n.applyMatrix3(nm).normalize();
          const wq = new THREE.Quaternion();
          (calGroupRef.current ?? e.object).getWorldQuaternion(wq);
          pushXRModelFaceNormal(n, wq);
          
          // Aplica/atualiza calibração se tivermos >= 2 pares
          if (xrCalibration.pairs.length >= 2) {
            const q = computeXRCalibrationQuaternion(xrCalibration.pairs);
            if (q) {
              useModelStore.getState().setCalibration(sceneModel.id, [q.x, q.y, q.z, q.w]);
            }
          }
          return;
        }

        // Calibração Virt/Real da Peça: captura os pontos virtuais.
        if (
          xrCalibration.modelId === sceneModel.id &&
          xrCalibration.alignType === 'virt-real' &&
          (xrCalibration.step === 'await-virtual-1' || xrCalibration.step === 'await-virtual-2' || xrCalibration.step === 'await-virtual-3') &&
          localFrameRef.current
        ) {
          const localPoint = localFrameRef.current.worldToLocal(e.point.clone());
          const localPivotPoint = localPoint.clone().sub(modelInfo.center);
          const stepNum = xrCalibration.step.endsWith('1') ? 1 : xrCalibration.step.endsWith('2') ? 2 : 3;

          if (stepNum === 3 && xrCalibration.realPoints.length >= 3 && topGroupRef.current) {
            const vPoints = [...xrCalibration.virtualPoints, localPivotPoint];
            const realWorldPoints = xrCalibration.realPoints;
            const parentPoints = realWorldPoints.map(rw => 
              topGroupRef.current!.worldToLocal(rw.clone())
            );

            const res = computeVirtRealTransform(vPoints, parentPoints);
            if (res) {
              const { quaternion, position } = res;
              useModelStore.getState().setCalibration(sceneModel.id, [quaternion.x, quaternion.y, quaternion.z, quaternion.w]);
              useModelStore.getState().setFineTuning({
                posX: position.x,
                posY: position.y,
                posZ: position.z,
                rotX: 0,
                rotY: 0,
                rotZ: 0,
              });
              pushXRVirtualPoint(localPivotPoint);
              toast.success("Peça virtual ajustada com sucesso na peça real!");
            } else {
              toast.error("Erro ao alinhar: pontos são colineares!");
            }
          } else {
            pushXRVirtualPoint(localPivotPoint);
            toast.success(`Ponto virtual ${stepNum} registrado!`);
          }
          return;
        }
      }}
    >
      {/* Translação */}
      <group position={[fineTuning.posX, fineTuning.posY, fineTuning.posZ]}>
        {/* Rotação e escala em volta do centro geométrico */}
        <group
          ref={ref}
          rotation={rotationEuler}
          scale={[s, s, s]}
        >
          {/* Rotação de calibração */}
          <group ref={calGroupRef} quaternion={calQuat}>
            {/* Sistema local do modelo com pivot no centro */}
            <group ref={localFrameRef} position={[-modelInfo.center.x, -modelInfo.center.y, -modelInfo.center.z]} userData={{ modelId: sceneModel.id }}>
              <primitive object={scene} />
              <XRLocalModelMeasurements modelId={sceneModel.id} />
            </group>
          </group>
        </group>
      </group>
    </group>
  );
}

/** Renders all NON-active models as static background (placement + grab apply only to active). */
function XRBackgroundModels() {
  const models = useModelStore((s) => s.models);
  const activeId = useModelStore((s) => s.activeModelId);
  return (
    <>
      {models.filter(m => m.id !== activeId).map((m) => (
        <XRModel key={m.id} sceneModel={m} />
      ))}
    </>
  );
}

/** Component that renders a laser from the camera (headset) to the grid landing target. */
function XRGridLandingLaser({ reticlePos }: { reticlePos: THREE.Vector3 | null }) {
  const { camera } = useThree();
  const geom = useMemo(() => new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(), new THREE.Vector3(0, 0, -1)]), []);
  const mat = useMemo(() => new THREE.LineBasicMaterial({ color: '#eab308', transparent: true, opacity: 0.6 }), []);
  const lineRef = useRef<THREE.Line>(null);

  useFrame(() => {
    if (lineRef.current && reticlePos) {
      const posAttr = geom.attributes.position as THREE.BufferAttribute;
      // Laser origin slightly below eyes
      posAttr.setXYZ(0, camera.position.x, camera.position.y - 0.05, camera.position.z);
      posAttr.setXYZ(1, reticlePos.x, reticlePos.y, reticlePos.z);
      posAttr.needsUpdate = true;
      geom.computeBoundingSphere();
      lineRef.current.visible = true;
    } else if (lineRef.current) {
      lineRef.current.visible = false;
    }
  });

  return <primitive ref={lineRef} object={new THREE.Line(geom, mat)} />;
}

/** Handles physics surface hit-testing using WebXR for grid and active model landing. */
function XRGridLandingHandler() {
  const gridLandingMode = useModelStore((s) => s.gridLandingMode);
  const gridY = useModelStore((s) => s.gridY);

  const reticleRef = useRef<THREE.Group>(null);
  const [reticlePos, setReticlePos] = useState<THREE.Vector3 | null>(null);

  // Continuous hit-test from viewer center
  useXRHitTest(
    gridLandingMode
      ? (results, getWorldMatrix) => {
          if (results.length === 0) {
            setReticlePos(null);
            return;
          }
          const matrixHelper = new THREE.Matrix4();
          getWorldMatrix(matrixHelper, results[0]);
          const positionHelper = new THREE.Vector3().setFromMatrixPosition(matrixHelper);
          setReticlePos(positionHelper.clone());
        }
      : undefined,
    'viewer'
  );

  // Trata a confirmação (clique/gatilho no óculos ou controle)
  const handleSelect = useCallback(() => {
    if (!gridLandingMode || !reticlePos) return;

    const targetY = reticlePos.y;
    const deltaY = targetY - gridY;

    // Desloca a peça ativa na mesma diferença (deltaY) para que ela "pouse junto"
    const state = useModelStore.getState();
    const activeModel = state.models.find(m => m.id === state.activeModelId);
    if (activeModel) {
      const ft = activeModel.fineTuning;
      state.setFineTuning({
        posY: ft.posY + deltaY,
      });
    }

    // Atualiza o grid Y no store
    useModelStore.setState({
      gridY: targetY,
      gridAutoFollow: false,
      gridLandingMode: false,
      showGrid: true,
    });

    toast.success("Grid e peça posicionados na superfície real!");
  }, [gridLandingMode, reticlePos, gridY]);

  // Atualiza posição da retícula a cada frame
  useFrame(() => {
    if (reticleRef.current) {
      if (reticlePos && gridLandingMode) {
        reticleRef.current.visible = true;
        reticleRef.current.position.copy(reticlePos);
      } else {
        reticleRef.current.visible = false;
      }
    }
  });

  if (!gridLandingMode) return null;

  return (
    <>
      <XRGridLandingLaser reticlePos={reticlePos} />
      
      {/* Retícula dourada premium */}
      <group ref={reticleRef}>
        <mesh onClick={handleSelect}>
          <ringGeometry args={[0.08, 0.1, 32]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} transparent opacity={0.8} />
        </mesh>
        <mesh rotation={[-Math.PI / 2, 0, 0]}>
          <ringGeometry args={[0.005, 0.015, 16]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} transparent opacity={0.6} />
        </mesh>
        <mesh>
          <ringGeometry args={[0.11, 0.115, 64]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} transparent opacity={0.3} />
        </mesh>
      </group>

      {/* Plano invisível de click no fundo */}
      <mesh
        position={[0, 0, -2]}
        onClick={handleSelect}
        visible={false}
      >
        <planeGeometry args={[10, 10]} />
        <meshBasicMaterial transparent opacity={0} />
      </mesh>
    </>
  );
}

/** Component that renders a laser from the camera (headset) to the virtual/real calibration target. */
function XRVirtRealCalibLaser({ reticlePos }: { reticlePos: THREE.Vector3 | null }) {
  const { camera } = useThree();
  const geom = useMemo(() => new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(), new THREE.Vector3(0, 0, -1)]), []);
  const mat = useMemo(() => new THREE.LineBasicMaterial({ color: '#eab308', transparent: true, opacity: 0.8, depthTest: false }), []);
  const lineRef = useRef<THREE.Line>(null);

  useFrame(() => {
    if (lineRef.current && reticlePos) {
      const posAttr = geom.attributes.position as THREE.BufferAttribute;
      // Laser origin slightly below eyes
      posAttr.setXYZ(0, camera.position.x, camera.position.y - 0.05, camera.position.z);
      posAttr.setXYZ(1, reticlePos.x, reticlePos.y, reticlePos.z);
      posAttr.needsUpdate = true;
      geom.computeBoundingSphere();
      lineRef.current.visible = true;
    } else if (lineRef.current) {
      lineRef.current.visible = false;
    }
  });

  return <primitive ref={lineRef} object={new THREE.Line(geom, mat)} />;
}

/** Handles physics surface hit-testing using WebXR for virtual-real piece alignment. */
function XRVirtRealCalibHandler() {
  const [, force] = useState(0);
  useEffect(() => subscribeXRCalibration(() => force(t => t + 1)), []);

  const isRealStep = xrCalibration.alignType === 'virt-real' && 
                     (xrCalibration.step === 'await-real-1' || 
                      xrCalibration.step === 'await-real-2' || 
                      xrCalibration.step === 'await-real-3');

  const reticleRef = useRef<THREE.Group>(null);
  const [reticlePos, setReticlePos] = useState<THREE.Vector3 | null>(null);

  // Continuous hit-test from viewer center
  useXRHitTest(
    isRealStep
      ? (results, getWorldMatrix) => {
          if (results.length === 0) {
            setReticlePos(null);
            return;
          }
          const matrixHelper = new THREE.Matrix4();
          getWorldMatrix(matrixHelper, results[0]);
          const positionHelper = new THREE.Vector3().setFromMatrixPosition(matrixHelper);
          setReticlePos(positionHelper.clone());
        }
      : undefined,
    'viewer'
  );

  const handleSelect = useCallback(() => {
    if (!isRealStep || !reticlePos) return;

    const stepNum = xrCalibration.step.endsWith('1') ? 1 : xrCalibration.step.endsWith('2') ? 2 : 3;
    pushXRRealPoint(reticlePos.clone());
    toast.success(`Ponto real ${stepNum} registrado!`);
  }, [isRealStep, reticlePos]);

  // Update reticle position
  useFrame(() => {
    if (reticleRef.current) {
      if (reticlePos && isRealStep) {
        reticleRef.current.visible = true;
        reticleRef.current.position.copy(reticlePos);
      } else {
        reticleRef.current.visible = false;
      }
    }
  });

  if (!isRealStep) return null;

  return (
    <>
      <XRVirtRealCalibLaser reticlePos={reticlePos} />
      
      {/* Golden reticle */}
      <group ref={reticleRef}>
        <mesh onClick={handleSelect}>
          <ringGeometry args={[0.08, 0.1, 32]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} transparent opacity={0.8} depthTest={false} />
        </mesh>
        <mesh rotation={[-Math.PI / 2, 0, 0]}>
          <ringGeometry args={[0.005, 0.015, 16]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} transparent opacity={0.6} depthTest={false} />
        </mesh>
        <mesh>
          <ringGeometry args={[0.11, 0.115, 64]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} transparent opacity={0.3} depthTest={false} />
        </mesh>
      </group>

      {/* Tap plane to capture select events */}
      <mesh
        position={[0, 0, -2]}
        onClick={handleSelect}
        visible={false}
      >
        <planeGeometry args={[10, 10]} />
        <meshBasicMaterial transparent opacity={0} />
      </mesh>
    </>
  );
}

/** Renders the currently-active model (the one wrapped by grab/placement). */
function XRActiveModel() {
  const models = useModelStore((s) => s.models);
  const activeId = useModelStore((s) => s.activeModelId);
  const active = models.find(m => m.id === activeId);
  if (!active) return null;
  return <XRModel sceneModel={active} />;
}

// ─── ControllerFineTuning ──────────────────────────────
// Joystick for slow numeric adjustments. Disabled while any grip is held
// (grab takes priority). Trigger pressure modulates speed: light = fine,
// strong = fast. Standard VR mapping: left=lateral/forward, right=rotY/height.
function ControllerFineTuning({ freeMove }: { freeMove: boolean }) {
  const { setFineTuning } = useModelStore();
  const session = useXR((s) => s.session);
  const isActiveLocked = useModelStore((s) => {
    const a = s.models.find(m => m.id === s.activeModelId);
    return !!a?.locked;
  });

  useFrame(() => {
    if (!session || isActiveLocked) return;
    const inputSources = session.inputSources;
    if (!inputSources) return;

    let leftAxes: number[] | null = null;
    let rightAxes: number[] | null = null;
    let leftTrig = 0;
    let rightTrig = 0;
    let gripHeld = false;
    let anyGripHeld = false;

    for (const source of inputSources) {
      const gp = source.gamepad;
      if (!gp) continue;
      const trigBtn = gp.buttons[0];
      const gripBtn = gp.buttons[1];
      const gripVal = gripBtn ? (gripBtn.value || (gripBtn.pressed ? 1 : 0)) : 0;
      if (gripBtn?.pressed) gripHeld = true;
      if (gripVal > 0.3) anyGripHeld = true; // matches grab hysteresis OFF
      const trigVal = trigBtn ? (trigBtn.value || (trigBtn.pressed ? 1 : 0)) : 0;
      if (source.handedness === 'left' && gp.axes.length >= 4) {
        leftAxes = [gp.axes[2], gp.axes[3]];
        leftTrig = trigVal;
      }
      if (source.handedness === 'right' && gp.axes.length >= 4) {
        rightAxes = [gp.axes[2], gp.axes[3]];
        rightTrig = trigVal;
      }
    }

    // Grab takes priority — joystick is disabled while grabbing
    if (anyGripHeld) return;
    // In freeMove mode, joystick always moves. Otherwise requires grip — but
    // grip is reserved for grab now, so freeMove=false essentially disables.
    if (!freeMove && !gripHeld) return;

    const baseStep = 0.001;
    const baseRot = 0.1;
    const deadzone = 0.15;
    // Trigger modulation: 0 → 0.3×, 1 → 3×
    const speedL = 0.3 + leftTrig * 2.7;
    const speedR = 0.3 + rightTrig * 2.7;
    // Quadratic acceleration on thumbstick value
    const curve = (v: number) => Math.sign(v) * v * v;

    const modelStore = useModelStore.getState();
    const ft = { ...modelStore.fineTuning };

    if (leftAxes) {
      // Left: X (horizontal) / Z forward-back (vertical, up = forward = -Z)
      if (Math.abs(leftAxes[0]) > deadzone) ft.posX += curve(leftAxes[0]) * baseStep * speedL;
      if (Math.abs(leftAxes[1]) > deadzone) ft.posZ += curve(leftAxes[1]) * baseStep * speedL;
    }
    if (rightAxes) {
      // Right: rotY (horizontal) / Y height (vertical, up = up)
      if (Math.abs(rightAxes[0]) > deadzone) ft.rotY += curve(rightAxes[0]) * baseRot * speedR;
      if (Math.abs(rightAxes[1]) > deadzone) ft.posY -= curve(rightAxes[1]) * baseStep * speedR;
    }

    setFineTuning(ft);
  });

  return null;
}

// Componente de renderização de texto compatível e seguro para WebXR
function XRMeasurementText({ text, color }: { text: string; color: string }) {
  const texture = useMemo(() => {
    const canvas = document.createElement('canvas');
    canvas.width = 256;
    canvas.height = 64;
    const ctx = canvas.getContext('2d');
    if (ctx) {
      // Limpa e desenha fundo semi-transparente
      ctx.fillStyle = 'rgba(11, 18, 32, 0.85)';
      ctx.beginPath();
      // Desenha retângulo arredondado manualmente
      const x = 0, y = 0, width = 256, height = 64, radius = 12;
      ctx.moveTo(x + radius, y);
      ctx.lineTo(x + width - radius, y);
      ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
      ctx.lineTo(x + width, y + height - radius);
      ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
      ctx.lineTo(x + radius, y + height);
      ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
      ctx.lineTo(x, y + radius);
      ctx.quadraticCurveTo(x, y, x + radius, y);
      ctx.closePath();
      ctx.fill();

      // Desenha borda sutil
      ctx.strokeStyle = color;
      ctx.lineWidth = 3;
      ctx.stroke();

      // Texto
      ctx.fillStyle = color;
      ctx.font = 'bold 24px monospace';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(text, 128, 32);
    }
    const tex = new THREE.CanvasTexture(canvas);
    tex.colorSpace = THREE.SRGBColorSpace;
    return tex;
  }, [text, color]);

  return (
    <mesh renderOrder={999}>
      <planeGeometry args={[0.08, 0.02]} />
      <meshBasicMaterial 
        map={texture} 
        transparent 
        depthTest={false} 
        side={THREE.DoubleSide} 
      />
    </mesh>
  );
}

// Componente de linha nativa seguro para WebXR
export function XRSafeLine({ a, b }: { a: [number, number, number]; b: [number, number, number] }) {
  const points = useMemo(() => [
    new THREE.Vector3(a[0], a[1], a[2]),
    new THREE.Vector3(b[0], b[1], b[2])
  ], [a, b]);

  const line = useMemo(() => {
    const geometry = new THREE.BufferGeometry().setFromPoints(points);
    const material = new THREE.LineBasicMaterial({ color: '#22c55e' });
    return new THREE.Line(geometry, material);
  }, [points]);

  return <primitive object={line} />;
}

// Componente para renderizar medições que pertencem a um modelo específico
export function XRLocalModelMeasurements({ modelId }: { modelId: string }) {
  const measurements = useModelStore((s) => s.measurements);
  const modelMeasurements = useMemo(() => {
    return measurements.filter(m => m.modelId === modelId);
  }, [measurements, modelId]);

  return (
    <>
      {modelMeasurements.map((m) => {
        const a: [number, number, number] = [m.pointA.x, m.pointA.y, m.pointA.z];
        const b: [number, number, number] = [m.pointB.x, m.pointB.y, m.pointB.z];
        const mid: [number, number, number] = [(a[0]+b[0])/2, (a[1]+b[1])/2, (a[2]+b[2])/2];
        const isHole = m.kind === 'hole';
        const color = isHole ? '#f59e0b' : '#3b82f6';
        const text = m.label ?? `${m.distanceMM.toFixed(1)} mm`;

        return (
          <group key={m.id}>
            {!isHole && (
              <>
                <mesh position={a}>
                  <sphereGeometry args={[0.003, 16, 16]} />
                  <meshBasicMaterial color="#22c55e" />
                </mesh>
                <mesh position={b}>
                  <sphereGeometry args={[0.003, 16, 16]} />
                  <meshBasicMaterial color="#22c55e" />
                </mesh>
                <XRSafeLine a={a} b={b} />
              </>
            )}
            <group position={mid}>
              <XRMeasurementText text={text} color={color} />
            </group>
          </group>
        );
      })}
    </>
  );
}

// ─── Measurement overlay (reused from ModelViewer) ─────
function XRMeasurementOverlay() {
  const measurements = useModelStore((s) => s.measurements);
  const measurePoints = useModelStore((s) => s.measurePoints);
  const snapPoint = useModelStore((s) => s.snapPoint);
  const measureMode = useModelStore((s) => s.measureMode);

  const globalMeasurements = useMemo(() => {
    return measurements.filter(m => !m.modelId);
  }, [measurements]);

  return (
    <>
      {measureMode && snapPoint && (
        <mesh position={[snapPoint.x, snapPoint.y, snapPoint.z]} rotation={[-Math.PI / 2, 0, 0]}>
          <ringGeometry args={[0.003, 0.005, 24]} />
          <meshBasicMaterial color="#eab308" side={THREE.DoubleSide} />
        </mesh>
      )}
      {measurePoints.length === 1 && (
        <mesh position={[measurePoints[0].x, measurePoints[0].y, measurePoints[0].z]}>
          <sphereGeometry args={[0.003, 16, 16]} />
          <meshBasicMaterial color="#e8a838" />
        </mesh>
      )}
      {globalMeasurements.map((m) => {
        const a: [number, number, number] = [m.pointA.x, m.pointA.y, m.pointA.z];
        const b: [number, number, number] = [m.pointB.x, m.pointB.y, m.pointB.z];
        const mid: [number, number, number] = [(a[0]+b[0])/2, (a[1]+b[1])/2, (a[2]+b[2])/2];
        const isHole = m.kind === 'hole';
        const color = isHole ? '#f59e0b' : '#3b82f6';
        const text = m.label ?? `${m.distanceMM.toFixed(1)} mm`;

        return (
          <group key={m.id}>
            {!isHole && (
              <>
                <mesh position={a}>
                  <sphereGeometry args={[0.003, 16, 16]} />
                  <meshBasicMaterial color="#22c55e" />
                </mesh>
                <mesh position={b}>
                  <sphereGeometry args={[0.003, 16, 16]} />
                  <meshBasicMaterial color="#22c55e" />
                </mesh>
                <XRSafeLine a={a} b={b} />
              </>
            )}
            <group position={mid}>
              <XRMeasurementText text={text} color={color} />
            </group>
          </group>
        );
      })}
    </>
  );
}

// ─── Snap handler for XR raycasting ────────────────────
function XRSnapHandler() {
  const { camera, scene, gl } = useThree();
  const measureMode = useModelStore((s) => s.measureMode);
  const setSnapPoint = useModelStore((s) => s.setSnapPoint);
  const addMeasurePoint = useModelStore((s) => s.addMeasurePoint);
  const snapPoint = useModelStore((s) => s.snapPoint);
  const raycaster = useMemo(() => new THREE.Raycaster(), []);
  const mouse = useMemo(() => new THREE.Vector2(), []);

  useEffect(() => {
    if (!measureMode) return;
    const onMove = (e: MouseEvent) => {
      const rect = gl.domElement.getBoundingClientRect();
      mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
      mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
    };
    gl.domElement.addEventListener('pointermove', onMove);
    return () => gl.domElement.removeEventListener('pointermove', onMove);
  }, [gl, mouse, measureMode]);

  useFrame(() => {
    // Em AR imersivo, a medição é feita pelo XRControllerMeasure (gatilho do controle).
    // Evita raycast pesado por frame que travava o Quest ao ativar "Medir".
    if (gl.xr.isPresenting) { setSnapPoint(null); return; }
    if (!measureMode) { setSnapPoint(null); return; }
    raycaster.setFromCamera(mouse, camera);
    const intersects = raycaster.intersectObjects(scene.children, true);
    const hit = intersects.find(i => {
      const obj = i.object;
      if (obj instanceof THREE.GridHelper) return false;
      if (obj instanceof THREE.Mesh && (obj.geometry instanceof THREE.SphereGeometry || obj.geometry instanceof THREE.RingGeometry)) return false;
      if (obj.userData.__edgeLine) return false;
      return obj instanceof THREE.Mesh;
    });
    if (hit && hit.object instanceof THREE.Mesh) {
      const canvas = gl.domElement;
      const snap = findNearestVertex(hit.object, hit.point, camera, { width: canvas.clientWidth, height: canvas.clientHeight }, 10);
      setSnapPoint(snap ? { x: snap.x, y: snap.y, z: snap.z } : null);
    } else {
      setSnapPoint(null);
    }
  });


  // Click to measure
  useEffect(() => {
    if (!measureMode) return;
    if (gl.xr.isPresenting) return; // Ignora cliques simulados do DOM quando o WebXR está ativo
    const onClick = (e: MouseEvent) => {
      if (snapPoint) {
        addMeasurePoint({ x: snapPoint.x, y: snapPoint.y, z: snapPoint.z });
        return;
      }
      const rect = gl.domElement.getBoundingClientRect();
      mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
      mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
      raycaster.setFromCamera(mouse, camera);
      const intersects = raycaster.intersectObjects(scene.children, true);
      const hit = intersects.find(i => i.object instanceof THREE.Mesh && !i.object.userData.__edgeLine);
      if (hit) addMeasurePoint({ x: hit.point.x, y: hit.point.y, z: hit.point.z });
    };
    gl.domElement.addEventListener('click', onClick);
    return () => gl.domElement.removeEventListener('click', onClick);
  }, [measureMode, snapPoint, gl, camera, scene, raycaster, mouse, addMeasurePoint]);

  useEffect(() => {
    gl.domElement.style.cursor = measureMode ? 'crosshair' : 'grab';
    return () => { gl.domElement.style.cursor = 'grab'; };
  }, [measureMode, gl]);

  return null;
}

// ─── Desktop Aligner Fallback for Virt/Real Calibration ─
function XRVirtRealDesktopAligner() {
  const { gl, camera, scene } = useThree();
  const [tick, setTick] = useState(0);

  useEffect(() => {
    return subscribeXRCalibration(() => setTick(t => t + 1));
  }, []);

  useEffect(() => {
    const isAligning = xrCalibration.alignType === 'virt-real' && 
                       (xrCalibration.step === 'await-real-1' || 
                        xrCalibration.step === 'await-real-2' || 
                        xrCalibration.step === 'await-real-3');
    if (!isAligning) return;
    if (gl.xr.isPresenting) return;

    const mouse = new THREE.Vector2();
    const raycaster = new THREE.Raycaster();

    const onClick = (e: MouseEvent) => {
      const rect = gl.domElement.getBoundingClientRect();
      mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
      mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
      raycaster.setFromCamera(mouse, camera);
      const intersects = raycaster.intersectObjects(scene.children, true);
      
      const activeModelId = useModelStore.getState().activeModelId;
      const hit = intersects.find(i => {
        if (i.object.userData?.__edgeLine) return false;
        let cur: THREE.Object3D | null = i.object;
        while (cur) {
          if (cur.userData?.modelId === activeModelId) return false;
          cur = cur.parent;
        }
        return true;
      });

      const point = hit ? hit.point.clone() : new THREE.Vector3(0, 0, 0);
      pushXRRealPoint(point);
      
      const stepNum = xrCalibration.step.endsWith('1') ? 1 : xrCalibration.step.endsWith('2') ? 2 : 3;
      toast.success(`Ponto real ${stepNum} registrado (Simulado)!`);
    };

    gl.domElement.addEventListener('click', onClick);
    return () => gl.domElement.removeEventListener('click', onClick);
  }, [gl, camera, scene, tick]);

  return null;
}

// ─── XR Grid ───────────────────────────────────────────
function XRGrid() {
  const showGrid = useModelStore((s) => s.showGrid);
  const gridY = useModelStore((s) => s.gridY);
  const activeModelId = useModelStore((s) => s.activeModelId);
  const activeModel = useModelStore((s) => s.models.find(m => m.id === activeModelId));
  const groupRef = useRef<THREE.Group>(null);

  useFrame(() => {
    if (!showGrid || !groupRef.current) return;

    let px = 0;
    let pz = 0;
    let ry = 0;

    if (activeModelGroupRef.current) {
      const g = activeModelGroupRef.current;
      const wp = new THREE.Vector3();
      g.getWorldPosition(wp);
      px = wp.x;
      pz = wp.z;

      const wq = new THREE.Quaternion();
      g.getWorldQuaternion(wq);
      const euler = new THREE.Euler().setFromQuaternion(wq, 'YXZ');
      ry = euler.y;
    } else if (activeModel) {
      px = activeModel.fineTuning.posX;
      pz = activeModel.fineTuning.posZ;
      ry = (activeModel.fineTuning.rotY * Math.PI) / 180;
    }

    groupRef.current.position.set(px, gridY, pz);
    groupRef.current.rotation.set(0, ry, 0);
  });

  if (!showGrid) return null;

  return (
    <group ref={groupRef}>
      <Grid
        infiniteGrid
        cellSize={0.01}
        sectionSize={0.1}
        cellThickness={0.5}
        sectionThickness={1}
        cellColor="#334155"
        sectionColor="#475569"
        fadeDistance={5}
        fadeStrength={1}
      />
    </group>
  );
}

/** Auto-follow grid to model bottom when enabled. */
function XRGridAutoFollower() {
  const models = useModelStore((s) => s.models);
  const { scene } = useThree();
  useEffect(() => {
    if (!useModelStore.getState().gridAutoFollow) return;
    const id = setTimeout(() => {
      if (!useModelStore.getState().gridAutoFollow) return;
      const box = new THREE.Box3();
      let has = false;
      scene.traverse((obj) => {
        if (obj instanceof THREE.Mesh && obj.geometry) {
          if (obj.geometry instanceof THREE.SphereGeometry) return;
          if (obj.geometry instanceof THREE.RingGeometry) return;
          if (obj.userData.__edgeLine) return;
          obj.updateWorldMatrix(true, false);
          const b = new THREE.Box3().setFromObject(obj);
          if (isFinite(b.min.y)) {
            if (!has) { box.copy(b); has = true; }
            else box.union(b);
          }
        }
      });
      if (has) useModelStore.setState({ gridY: box.min.y - 0.005 });
    }, 150);
    return () => clearTimeout(id);
  }, [models, scene]);
  return null;
}

// ImageTrackingAnchor removed — replaced by XRHitTestPlacement

// ─── XRSession Page ────────────────────────────────────
const XRSession = () => {
  const navigate = useNavigate();
  const { model, anchorMode, setAnchorMode } = useModelStore();
  const isActiveLocked = useModelStore((s) => {
    const a = s.models.find(m => m.id === s.activeModelId);
    return !!a?.locked;
  });
  const [inXR, setInXR] = useState(false);
  const [freeMove, setFreeMove] = useState(true);
  const [placementMode, setPlacementMode] = useState(true); // start in placement mode
  const [snapToPlanes, setSnapToPlanes] = useState(true);
  // Zoom por grip duplo — toggle real, padrão ligado.
  const [allowScale, setAllowScale] = useState(true);
  const [liveCode, setLiveCode] = useState<string | null>(null);
  const [liveViewers, setLiveViewers] = useState(0);
  // Rig que envolve <XROrigin/> — locomoção por joystick escreve aqui.
  const rigRef = useRef<THREE.Group>(null);
  // DEVKIT: simXR forces in-XR rendering on desktop without a real WebXR session
  const devkit = useDevKit();
  const [simXR, setSimXR] = useState(false);
  const effectiveInXR = inXR || simXR;
  // Indica que enterAR() foi chamado mas a sessão ainda não começou — previne auto-return prematuro
  const [isEnteringAR, setIsEnteringAR] = useState(false);
  const [hasClickedEnter, setHasClickedEnter] = useState(false);

  useEffect(() => {
    if (!model) navigate('/');
  }, [model, navigate]);

  // Detecta quando a sessão XR de fato começa
  useEffect(() => {
    const unsubscribe = store.subscribe((state) => {
      const session = state.session;
      if (session && !inXR) {
        console.log('[XR] ✅ Sessão AR ativa!');
        setInXR(true);
        setIsEnteringAR(false);
        setAnchorMode('manual');
        toast.success('Sessão AR iniciada!');
        session.addEventListener('end', () => {
          console.log('[XR] ❌ Sessão AR encerrada');
          setInXR(false);
          setHasClickedEnter(false);
          navigate('/viewer');
        });
      }
    });
    return unsubscribe;
  }, [inXR, setAnchorMode, navigate]);

  // Flag que indica que o usuário pediu para entrar no AR (enterAR chamado).
  // Usada para bloquear o auto-return durante o onboarding do WebXR.
  useEffect(() => {
    // Se inXR virou true mas isEnteringAR é true, a sessão começou — limpa o flag
    if (inXR && isEnteringAR) {
      setIsEnteringAR(false);
    }
  }, [inXR, isEnteringAR]);

  // Expõe setIsEnteringAR para o Viewer via window (permite marcar "entrando" antes de navegar)
  useEffect(() => {
    (window as unknown as { __setXrEntering?: (v: boolean) => void }).__setXrEntering = setIsEnteringAR;
  }, []);

  const handleDownloadMarker = useCallback(async () => {
    const url = await generateMarkerDownloadURL();
    const a = document.createElement('a');
    a.href = url;
    a.download = 'SteelXR_Marker.png';
    a.click();
    URL.revokeObjectURL(url);
    toast.success('Marcador baixado — Imprima em 15×15cm');
  }, []);

  if (!model) return null;

  return (
    <div className="flex h-screen flex-col bg-background">
      {/* Header */}
      <header className="flex items-center justify-between border-b bg-card px-4 py-3 z-10">
        <div className="flex items-center gap-2">
          <Button variant="ghost" size="icon" onClick={() => navigate('/viewer')} title="Voltar ao Viewer">
            <ArrowLeft className="h-5 w-5" />
          </Button>
          <Button variant="ghost" size="icon" onClick={() => navigate('/')} title="Tela inicial">
            <Home className="h-5 w-5" />
          </Button>
          <h1 className="font-mono text-sm font-semibold text-foreground">
            Modo <span className="text-primary">XR Imersivo</span>
          </h1>
        </div>

        <div className="flex items-center gap-2">
          {inXR && (
            <span className="font-mono text-xs text-primary flex items-center gap-1.5">
              <span className="h-2 w-2 rounded-full bg-primary animate-pulse" />
              XR Ativo
            </span>
          )}
        </div>
      </header>

      {/* 3D Canvas */}
      <div className="flex-1 relative">
        <Canvas
          gl={{ antialias: true, alpha: true, powerPreference: 'high-performance', preserveDrawingBuffer: true }}
          camera={{ position: [1.5, 1.2, 1.5], fov: 50, near: 0.01, far: 100 }}
          className="!bg-transparent"
          onCreated={({ gl }) => {
            gl.setPixelRatio(Math.min(window.devicePixelRatio, 1.5));
            gl.setClearColor(0x000000, 0);
          }}
        >
          <XR store={store}>
            <ambientLight intensity={0.8} />
            <directionalLight position={[3, 5, 3]} intensity={1.2} />
            <directionalLight position={[-3, 3, -3]} intensity={0.4} />

            <group ref={(el) => {
              (rigRef as React.MutableRefObject<THREE.Group | null>).current = el;
              useModelStore.getState().setXRRig(el);
            }}>
              <XROrigin />
            </group>

            {effectiveInXR ? (
              <>
                {/* In XR (or SimXR): all models share the same placement origin so
                    switching active doesn't make others appear to "disappear".
                    Only the ACTIVE model receives grab transforms. */}
                {simXR ? (
                  <group position={[0, 1.0, -1.2]}>
                    <XRBackgroundModels />
                    <XRGrabbable
                      allowScale={allowScale}
                      lockedActive={isActiveLocked}
                      onGrabStart={() => { if (placementMode) setPlacementMode(false); }}
                    >
                      <XRActiveModel />
                    </XRGrabbable>
                  </group>
                ) : (
                  <XRHitTestPlacement
                    placementMode={placementMode}
                    snapToPlanes={snapToPlanes}
                    onPlace={() => {
                      setPlacementMode(false);
                      toast.success('Modelo posicionado na superfície!');
                    }}
                  >
                    <XRBackgroundModels />
                    <XRGrabbable
                      allowScale={allowScale}
                      lockedActive={isActiveLocked}
                      onGrabStart={() => { if (placementMode) setPlacementMode(false); }}
                    >
                      <XRActiveModel />
                    </XRGrabbable>
                  </XRHitTestPlacement>
                )}

                <XRMeasurementOverlay />
                <XRControllerMeasure />
                <ControllerLocomotion rigRef={rigRef} />
                <VisibilityApplier />
                <XRGridLandingHandler />
                <XRVirtRealCalibHandler />

                {/* In-world HUD — visible inside passthrough where DOM overlays cannot reach */}
                <XRHudInWorld
                  freeMove={freeMove}
                  onToggleFreeMove={() => setFreeMove(!freeMove)}
                  placementMode={placementMode}
                  onTogglePlacement={() => setPlacementMode(!placementMode)}
                  snapToPlanes={snapToPlanes}
                  onToggleSnap={() => setSnapToPlanes(!snapToPlanes)}
                  allowScale={allowScale}
                  onToggleAllowScale={() => setAllowScale(!allowScale)}
                  liveCode={liveCode}
                  liveViewers={liveViewers}
                  onStartLive={() => (window as unknown as { __trackSteelStartLive?: () => void }).__trackSteelStartLive?.()}
                  onStopLive={() => (window as unknown as { __trackSteelStopLive?: () => void }).__trackSteelStopLive?.()}
                />

                {/* Opaque mirror canvas used as the WebRTC source while in AR */}
                <XRBroadcastMirror enabled />

                {/* DEVKIT: fake controllers visible in scene + keyboard driver */}
                {devkit && simXR && <FakeControllers />}
                {/* DEVKIT: orbit camera in SimXR so you can navigate around the model */}
                {simXR && (
                  <OrbitControls
                    makeDefault
                    enableDamping
                    dampingFactor={0.1}
                    minDistance={0.05}
                    maxDistance={50}
                    target={[0, 1.0, -1.2]}
                  />
                )}
              </>
            ) : (
              <>
                {/* Desktop preview (no headset): show all models with OrbitControls */}
                <group position={[0, 0, 0]}>
                  <XRBackgroundModels />
                  <XRActiveModel />
                </group>
                <XRMeasurementOverlay />
                <OrbitControls
                  makeDefault
                  enableDamping
                  dampingFactor={0.1}
                  minDistance={0.05}
                  maxDistance={50}
                  target={[0, 0, 0]}
                />
              </>
            )}

            <XRSnapHandler />
            <XRVirtRealDesktopAligner />
            <XRGrid />
            <XRGridAutoFollower />
          </XR>
        </Canvas>

        {/* Onboarding do AR */}
        {!effectiveInXR && (
          <div className="absolute inset-0 z-50 flex items-center justify-center bg-slate-950/85 backdrop-blur-md p-6">
            <div className="w-full max-w-md border border-primary/20 bg-slate-900/95 rounded-2xl p-8 shadow-2xl text-center space-y-6 glow-primary">
              <div className="flex justify-center">
                <div className="h-16 w-16 items-center justify-center flex rounded-full bg-primary/10 border border-primary/30 animate-pulse">
                  <Glasses className="h-8 w-8 text-primary" />
                </div>
              </div>
              
              <div className="space-y-2">
                <h2 className="text-xl font-semibold tracking-tight text-foreground font-mono">
                  Pronto para entrar no <span className="text-primary">Modo AR</span>?
                </h2>
                <p className="text-sm text-muted-foreground">
                  Você está prestes a carregar o modelo em escala real 1:1 no seu ambiente físico.
                </p>
              </div>

              {/* Informações da Peça */}
              <div className="rounded-lg border border-border bg-slate-950/50 p-4 text-left space-y-2 font-mono text-xs">
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Modelo Ativo:</span>
                  <span className="text-foreground truncate max-w-[200px]" title={model.fileName}>{model.fileName}</span>
                </div>
                <div className="flex justify-between">
                  <span className="text-muted-foreground">Tamanho:</span>
                  <span className="text-foreground">{(model.fileSize / (1024 * 1024)).toFixed(2)} MB</span>
                </div>
              </div>

              {/* Dicas Rápidas */}
              <div className="text-left space-y-2.5 rounded-lg bg-primary/5 border border-primary/15 p-4 text-xs">
                <h3 className="font-semibold text-primary font-mono flex items-center gap-1.5">
                  💡 Guia de Controles Rápidos:
                </h3>
                <ul className="space-y-1.5 text-muted-foreground list-disc pl-4">
                  <li><strong>Teletransporte:</strong> Thumbstick para frente. Solte para teleportar.</li>
                  <li><strong>Escala Real (1:1):</strong> Aponte o feixe para a peça e teletransporte nela.</li>
                  <li><strong>Mover Peça:</strong> Segure o Grip de qualquer controle para arrastar.</li>
                  <li><strong>Girar/Zoom:</strong> Ambas as miras na peça, segure ambos os Grips e mova as mãos.</li>
                  <li><strong>Menu do App:</strong> Botões A/B/X/Y abrem/fecham o menu flutuante.</li>
                </ul>
              </div>

              {/* Ações */}
              <div className="flex flex-col gap-3 pt-2">
                <Button
                  className="h-12 text-sm font-semibold glow-primary w-full gap-2 text-primary-foreground"
                  disabled={hasClickedEnter}
                  onClick={async () => {
                    setHasClickedEnter(true);
                    try {
                      await store.enterAR();
                    } catch (err) {
                      console.error("[XR] Falha ao iniciar AR:", err);
                      toast.error("Não foi possível iniciar o modo AR. Verifique se o Quest 3 está conectado.");
                      setHasClickedEnter(false);
                    }
                  }}
                >
                  {hasClickedEnter ? <Loader2 className="h-5 w-5 animate-spin" /> : <Glasses className="h-5 w-5 animate-bounce" />}
                  {hasClickedEnter ? 'Aguardando Permissão AR...' : 'Iniciar Visualização AR'}
                </Button>
                
                <Button
                  variant="outline"
                  className="h-12 text-sm font-medium border-muted-foreground/20 text-muted-foreground hover:bg-slate-800 hover:text-foreground w-full"
                  onClick={() => navigate('/viewer')}
                >
                  Voltar ao Viewer
                </Button>
              </div>
            </div>
          </div>
        )}

        {/* Floating DOM HUD overlay — only visible OUTSIDE passthrough.
            Inside AR, the DOM is occluded by the headset compositor; the
            in-world XRHudInWorld replaces it. */}
        <div className={inXR ? 'hidden' : 'contents'}>
          <XRHud
            freeMove={freeMove}
            onToggleFreeMove={() => setFreeMove(!freeMove)}
            placementMode={placementMode}
            onTogglePlacement={() => setPlacementMode(!placementMode)}
            snapToPlanes={snapToPlanes}
            onToggleSnap={() => setSnapToPlanes(!snapToPlanes)}
            allowScale={allowScale}
            onToggleAllowScale={() => setAllowScale(!allowScale)}
          />
        </div>

        {/* Hidden ShareButton instance — registers window.__trackSteelStartLive
            so the in-world Share tab can trigger broadcasts. Also keeps live
            state in sync with the in-XR HUD. */}
        <div className="hidden">
          <ShareButton
            onHandleChange={(h) => setLiveCode(h?.code ?? null)}
            onViewerCountChange={setLiveViewers}
          />
        </div>

        {/* DEVKIT: floating diagnostic panel + SimXR toggle */}
        {devkit && (
          <DevPanel simXR={simXR} onToggleSimXR={() => setSimXR((v) => !v)} />
        )}
      </div>
    </div>
  );
};

export default XRSession;
