import { useRef, useMemo, useEffect, useState } from 'react';
import { useFrame, ThreeEvent } from '@react-three/fiber';
import * as THREE from 'three';
import { pushXRCubeFace } from './xrCalibrationBus';
import { getModelLocalGroup } from '@/lib/modelTransforms';

function makeFaceTexture(label: string, accent: boolean): THREE.CanvasTexture {
  const size = 256;
  const c = document.createElement('canvas');
  c.width = size;
  c.height = size;
  const ctx = c.getContext('2d')!;
  const grad = ctx.createLinearGradient(0, 0, 0, size);
  grad.addColorStop(0, accent ? '#1e3a8a' : '#111827');
  grad.addColorStop(1, accent ? '#0f172a' : '#030712');
  ctx.fillStyle = grad;
  ctx.fillRect(0, 0, size, size);
  ctx.strokeStyle = '#3b82f6';
  ctx.lineWidth = 8;
  ctx.strokeRect(4, 4, size - 8, size - 8);
  ctx.fillStyle = '#ffffff';
  ctx.font = '700 52px monospace';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.shadowColor = '#3b82f6';
  ctx.shadowBlur = 10;
  ctx.fillText(label, size / 2, size / 2);
  const tex = new THREE.CanvasTexture(c);
  tex.anisotropy = 4;
  tex.needsUpdate = true;
  return tex;
}

const FACE_DEFS: { label: string; dir: [number, number, number] }[] = [
  { label: 'DIR',    dir: [ 1, 0, 0] },
  { label: 'ESQ',    dir: [-1, 0, 0] },
  { label: 'TOPO',   dir: [ 0, 1, 0] },
  { label: 'BASE',   dir: [ 0,-1, 0] },
  { label: 'FRENTE', dir: [ 0, 0, 1] },
  { label: 'ATRÁS',  dir: [ 0, 0,-1] },
];

export function XRViewCube({ activeModelId, size = 0.06 }: { activeModelId: string | null; size?: number }) {
  const groupRef = useRef<THREE.Group>(null);
  const [hover, setHover] = useState<number | null>(null);

  const materials = useMemo(() => {
    return FACE_DEFS.map((f, i) => {
      const tex = makeFaceTexture(f.label, false);
      const mat = new THREE.MeshBasicMaterial({ map: tex });
      mat.userData.baseTex = tex;
      mat.userData.hoverTex = makeFaceTexture(f.label, true);
      mat.userData.faceIndex = i;
      return mat;
    });
  }, []);

  useEffect(() => {
    return () => {
      materials.forEach((m) => {
        m.userData.baseTex?.dispose?.();
        m.userData.hoverTex?.dispose?.();
        m.dispose();
      });
    };
  }, [materials]);

  useEffect(() => {
    materials.forEach((m, i) => {
      m.map = i === hover ? m.userData.hoverTex : m.userData.baseTex;
      m.needsUpdate = true;
    });
  }, [hover, materials]);

  const modelQuat = useMemo(() => new THREE.Quaternion(), []);

  const getModelWorldQuat = (): THREE.Quaternion => {
    const g = getModelLocalGroup(activeModelId);
    if (g) {
      g.updateWorldMatrix(true, false);
      g.getWorldQuaternion(modelQuat);
      return modelQuat;
    }
    modelQuat.identity();
    return modelQuat;
  };

  useFrame(() => {
    if (groupRef.current) {
      // Sincroniza a rotação do cubo no HUD AR com a rotação do modelo ativo no mundo AR.
      // Desta forma, o cubo reflete a orientação 3D da peça.
      groupRef.current.quaternion.copy(getModelWorldQuat());
    }
  });

  const onClick = (e: ThreeEvent<MouseEvent>) => {
    e.stopPropagation();
    const idx = e.face?.materialIndex;
    if (idx == null) return;
    const def = FACE_DEFS[idx];
    if (!def) return;
    const dirWorld = new THREE.Vector3(...def.dir).applyQuaternion(getModelWorldQuat()).normalize();
    pushXRCubeFace(dirWorld);
  };

  return (
    <group ref={groupRef}>
      <mesh
        material={materials}
        onClick={onClick}
        onPointerOver={(e) => {
          e.stopPropagation();
          const idx = e.face?.materialIndex ?? null;
          setHover(idx);
        }}
        onPointerOut={(e) => {
          e.stopPropagation();
          setHover(null);
        }}
      >
        <boxGeometry args={[size, size, size]} />
      </mesh>
    </group>
  );
}
