import { useEffect, useRef, useMemo, useCallback, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { useGLTF } from '@react-three/drei';
import { XR, createXRStore, useXR, XROrigin } from '@react-three/xr';
import * as THREE from 'three';
import { useModelStore } from '@/stores/useModelStore';
import { toast } from 'sonner';
import { ArrowLeft, Move, RotateCw, QrCode, Download, Crosshair } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { generateMarkerDownloadURL } from '@/lib/trackingMarker';

// --- XR Store singleton ---
let xrStoreInstance: ReturnType<typeof createXRStore> | null = null;

function getOrCreateXRStore() {
  if (xrStoreInstance) return xrStoreInstance;

  // Only emulate when on localhost AND no native XR support
  const shouldEmulate =
    typeof window !== 'undefined' &&
    window.location.hostname === 'localhost' &&
    !navigator.xr;

  xrStoreInstance = createXRStore({
    emulate: shouldEmulate ? 'metaQuest3' : false,
    hand: { left: true, right: true },
    controller: { left: true, right: true },
  });

  return xrStoreInstance;
}

// ─── XRModel ───────────────────────────────────────────
function XRModel({ url }: { url: string }) {
  const { scene } = useGLTF(url);
  const ref = useRef<THREE.Group>(null);
  const fineTuning = useModelStore((s) => s.fineTuning);
  const opacity = useModelStore((s) => s.opacity);
  const renderMode = useModelStore((s) => s.renderMode);
  const checklist = useModelStore((s) => s.checklist);

  const modelInfo = useMemo(() => {
    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(() => {
    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 materials = Array.isArray(child.material) ? child.material : [child.material];
        materials.forEach((mat: THREE.Material) => {
          if (mat instanceof THREE.MeshStandardMaterial) {
            mat.transparent = opacity < 1;
            mat.opacity = opacity;
            mat.wireframe = renderMode === 'wireframe';
            mat.needsUpdate = true;
            if (hasRejected) {
              mat.color.setHSL(0, 0.7, 0.5);
            } else if (allApproved) {
              mat.color.setHSL(0.38, 0.7, 0.45);
            } else {
              mat.color.set(0x8899aa);
            }
          }
        });
      }
    });
  }, [scene, opacity, renderMode, checklist]);

  const rotYRad = (fineTuning.rotY * Math.PI) / 180;

  return (
    <group
      ref={ref}
      position={[
        -modelInfo.center.x + fineTuning.posX,
        -modelInfo.center.y + fineTuning.posY,
        -modelInfo.center.z + fineTuning.posZ,
      ]}
      rotation={[0, rotYRad, 0]}
    >
      <primitive object={scene} />
    </group>
  );
}

// ─── ControllerFineTuning ──────────────────────────────
function ControllerFineTuning() {
  const { setFineTuning } = useModelStore();
  const session = useXR((s) => s.session);

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

    let leftAxes: number[] | null = null;
    let rightAxes: number[] | null = null;
    let gripHeld = false;

    for (const source of inputSources) {
      const gp = source.gamepad;
      if (!gp) continue;
      const gripButton = gp.buttons[2];
      if (gripButton && gripButton.pressed) gripHeld = true;
      if (source.handedness === 'left' && gp.axes.length >= 4) {
        leftAxes = [gp.axes[2], gp.axes[3]];
      }
      if (source.handedness === 'right' && gp.axes.length >= 4) {
        rightAxes = [gp.axes[2], gp.axes[3]];
      }
    }

    if (!gripHeld) return;

    const posStep = 0.001;
    const rotStep = 0.1;
    const deadzone = 0.15;
    const store = useModelStore.getState();
    const ft = { ...store.fineTuning };

    if (leftAxes) {
      if (Math.abs(leftAxes[0]) > deadzone) ft.posX += leftAxes[0] * posStep;
      if (Math.abs(leftAxes[1]) > deadzone) ft.posY -= leftAxes[1] * posStep;
    }
    if (rightAxes) {
      if (Math.abs(rightAxes[1]) > deadzone) ft.posZ += rightAxes[1] * posStep;
      if (Math.abs(rightAxes[0]) > deadzone) ft.rotY += rightAxes[0] * rotStep;
    }

    setFineTuning(ft);
  });

  return null;
}

// ─── ImageTrackingAnchor ───────────────────────────────
function ImageTrackingAnchor({ children }: { children: React.ReactNode }) {
  const groupRef = useRef<THREE.Group>(null);
  const session = useXR((s) => s.session);
  const { gl } = useThree();
  const { setAnchorMode } = useModelStore();
  const trackingActive = useRef(false);

  useFrame((_, __, frame: any) => {
    if (!frame || !session || !groupRef.current) return;

    try {
      const results = frame.getImageTrackingResults?.();
      if (results && results.length > 0) {
        for (const result of results) {
          if (result.trackingState === 'tracked' || result.trackingState === 'emulated') {
            const refSpace = gl.xr.getReferenceSpace();
            if (!refSpace) continue;

            const pose = frame.getPose(result.imageSpace, refSpace);
            if (pose) {
              const pos = pose.transform.position;
              const ori = pose.transform.orientation;

              groupRef.current.position.set(pos.x, pos.y, pos.z);
              groupRef.current.quaternion.set(ori.x, ori.y, ori.z, ori.w);

              if (!trackingActive.current) {
                trackingActive.current = true;
                setAnchorMode('tracking');
                toast.success('QR Code detectado — Modelo ancorado!');
              }
              return;
            }
          }
        }
      }
    } catch {
      // getImageTrackingResults not available
    }

    if (trackingActive.current) return;

    // Manual fallback — place 1.5m in front
    groupRef.current.position.set(0, 0, -1.5);
    groupRef.current.quaternion.identity();
  });

  return <group ref={groupRef}>{children}</group>;
}

// ─── XRSession Page ────────────────────────────────────
const XRSession = () => {
  const navigate = useNavigate();
  const { model, anchorMode, setAnchorMode } = useModelStore();
  const [inXR, setInXR] = useState(false);
  const [store] = useState(() => getOrCreateXRStore());

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

  const handleEnterAR = useCallback(async () => {
    try {
      const session = await store.enterAR();
      if (session) {
        session.addEventListener('end', () => {
          setInXR(false);
          setAnchorMode('manual');
        });
        setInXR(true);
        setAnchorMode('manual');
        toast.success('Sessão XR iniciada!');
      }
    } catch (err: any) {
      console.error('XR error:', err);
      toast.error(`Falha ao iniciar XR: ${err.message}`);
    }
  }, [store, setAnchorMode]);

  const handleDownloadMarker = useCallback(async () => {
    const url = await generateMarkerDownloadURL();
    const a = document.createElement('a');
    a.href = url;
    a.download = 'TrackkSteelXR_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-3">
          <Button variant="ghost" size="icon" onClick={() => navigate('/viewer')}>
            <ArrowLeft 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 && (
            <>
              <Button variant="outline" size="sm" className="gap-1.5" onClick={handleDownloadMarker}>
                <Download className="h-3.5 w-3.5" />
                <span className="font-mono text-xs">Marcador QR</span>
              </Button>
              <Button className="gap-2 glow-primary" onClick={handleEnterAR}>
                Iniciar Sessão AR
              </Button>
            </>
          )}

          {inXR && (
            <div className="flex items-center gap-3">
              <span className="font-mono text-xs text-success flex items-center gap-1.5">
                <span className="h-2 w-2 rounded-full bg-success animate-pulse" />
                XR Ativo
              </span>
              {anchorMode === 'tracking' ? (
                <span className="font-mono text-[10px] text-primary flex items-center gap-1">
                  <QrCode className="h-3 w-3" />
                  Tracking
                </span>
              ) : (
                <span className="font-mono text-[10px] text-muted-foreground flex items-center gap-1">
                  <Crosshair className="h-3 w-3" />
                  Manual
                </span>
              )}
            </div>
          )}
        </div>
      </header>

      {/* 3D Canvas */}
      <div className="flex-1 relative">
        <Canvas
          gl={{ antialias: true, alpha: true, powerPreference: 'high-performance' }}
          camera={{ position: [0, 1.6, 0], 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} />

            <XROrigin />

            <ImageTrackingAnchor>
              <XRModel url={model.url} />
            </ImageTrackingAnchor>

            <ControllerFineTuning />
          </XR>
        </Canvas>

        {/* Floating HUD overlay */}
        <div className="absolute bottom-4 left-4 right-4 z-10 pointer-events-none">
          <div className="pointer-events-auto inline-flex flex-wrap gap-3 rounded-lg border bg-card/90 backdrop-blur-sm p-3 shadow-lg">
            <div className="flex items-center gap-2">
              <QrCode className="h-3.5 w-3.5 text-primary" />
              <span className="font-mono text-[10px] text-muted-foreground">
                {anchorMode === 'tracking' ? '● QR Detectado' : '○ Buscando QR…'}
              </span>
            </div>
            <div className="flex items-center gap-2">
              <Move className="h-3.5 w-3.5 text-primary" />
              <span className="font-mono text-[10px] text-muted-foreground">
                Grip + Joy Esq: X/Y
              </span>
            </div>
            <div className="flex items-center gap-2">
              <RotateCw className="h-3.5 w-3.5 text-primary" />
              <span className="font-mono text-[10px] text-muted-foreground">
                Grip + Joy Dir: Z/Rot
              </span>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default XRSession;
