// ── STELLAR CARD GALLERY ─────────────────────────────────────────
// Pure Three.js starfield + CSS 2.5D projection — responsive galaxy

/* ── Responsive dimension helper ── */
function getResponsiveDims() {
  const w = window.innerWidth;
  const h = window.innerHeight;
  const mobile = w < 768;
  const tablet = w >= 768 && w < 1024;

  // Constraint: maxRadius(20) * SCALE + CARD_W/2  <  w/2
  // Mobile:  (195 - 48) / 20 = 7.35 → SCALE=7, CARD_W=96
  // Tablet:  (384 - 65) / 20 = 15.9 → SCALE=15, CARD_W=130
  // Desktop: (640 - 80) / 20 = 28   → SCALE=28, CARD_W=160
  //
  // FOV controls depth "punch": lower = stronger perspective separation.
  // Original three.js scene had very strong perspective; we need FOV≈280 on
  // mobile so front-cards appear ~1.9x bigger than back-cards, matching the
  // original "galaxy" feel instead of flat clustering.
  return {
    mobile,
    tablet,
    CARD_W:  mobile ? 96   : tablet ? 130 : 160,
    CARD_H:  mobile ? 125  : tablet ? 169 : 208,
    SCALE:   mobile ? 7    : tablet ? 15  : 28,
    FOV:     mobile ? 280  : tablet ? 600 : 900,
    originY: mobile ? '56%' : '50%',
    rotX0:   mobile ? 10   : 15,   // initial tilt — flatter on mobile
  };
}

/* ── Starfield (pure Three.js) ── */
function StarfieldBackground() {
  const mountRef = React.useRef(null);

  React.useEffect(() => {
    const el = mountRef.current;
    if (!el) return;

    const scene    = new THREE.Scene();
    const camera   = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 2000);
    const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setClearColor(0x000000, 1);
    el.appendChild(renderer.domElement);

    const count = 10000;
    const geom  = new THREE.BufferGeometry();
    const pos   = new Float32Array(count * 3);
    for (let i = 0; i < count; i++) {
      pos[i * 3]     = (Math.random() - 0.5) * 2000;
      pos[i * 3 + 1] = (Math.random() - 0.5) * 2000;
      pos[i * 3 + 2] = (Math.random() - 0.5) * 2000;
    }
    geom.setAttribute('position', new THREE.BufferAttribute(pos, 3));
    const mat   = new THREE.PointsMaterial({ color: 0xffffff, size: 0.7, sizeAttenuation: true });
    const stars = new THREE.Points(geom, mat);
    scene.add(stars);
    camera.position.z = 10;

    let animId;
    const tick = () => {
      animId = requestAnimationFrame(tick);
      stars.rotation.y += 0.0001;
      stars.rotation.x += 0.00005;
      renderer.render(scene, camera);
    };
    tick();

    const onResize = () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    };
    window.addEventListener('resize', onResize);

    return () => {
      window.removeEventListener('resize', onResize);
      cancelAnimationFrame(animId);
      if (el.contains(renderer.domElement)) el.removeChild(renderer.domElement);
      renderer.dispose();
      geom.dispose();
      mat.dispose();
    };
  }, []);

  return (
    <div ref={mountRef}
      style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', zIndex: 0 }}
    />
  );
}

/* ── Icons ── */
function DownloadIcon() {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
      <polyline points="7 10 12 15 17 10" />
      <line x1="12" y1="15" x2="12" y2="3" />
    </svg>
  );
}

function HeartIcon({ filled }) {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24"
      fill={filled ? 'currentColor' : 'none'} stroke="currentColor"
      strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />
    </svg>
  );
}

function XIcon() {
  return (
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
      strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
      <line x1="18" y1="6" x2="6" y2="18" />
      <line x1="6" y1="6" x2="18" y2="18" />
    </svg>
  );
}

/* ── Floating Card — ref forwarded so parent can update transform in rAF ── */
const FloatingCard = React.forwardRef(function FloatingCard(
  { card, onSelect, dragDistRef, cardW, cardH },
  ref
) {
  const [hovered, setHovered] = React.useState(false);

  return (
    <div
      ref={ref}
      onClick={(e) => { e.stopPropagation(); if (dragDistRef.current < 10) onSelect(card); }}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{
        position: 'absolute', left: 0, top: 0,
        width: cardW + 'px', height: cardH + 'px',
        transformOrigin: (cardW / 2) + 'px ' + (cardH / 2) + 'px',
        willChange: 'transform',
      }}
    >
      <div style={{
        width: '100%', height: '100%',
        borderRadius: '12px', overflow: 'hidden',
        background: '#1F2121', padding: '9px',
        display: 'flex', flexDirection: 'column',
        boxSizing: 'border-box',
        boxShadow: hovered
          ? '0 20px 40px rgba(49,184,198,0.5), 0 0 24px rgba(49,184,198,0.3)'
          : '0 12px 28px rgba(0,0,0,0.65)',
        border: hovered
          ? '1.5px solid rgba(49,184,198,0.6)'
          : '1px solid rgba(255,255,255,0.1)',
        transform: hovered ? 'scale(1.08)' : 'scale(1)',
        transition: 'box-shadow 0.3s ease, border-color 0.3s ease, transform 0.3s ease',
        cursor: 'pointer',
      }}>
        <img
          src={card.imageUrl} alt={card.alt}
          style={{ width: '100%', flex: 1, minHeight: 0, objectFit: 'cover', borderRadius: '7px', display: 'block' }}
          loading="lazy" draggable={false}
        />
        <p style={{
          color: 'white', fontSize: '10px', fontWeight: 500,
          textAlign: 'center', marginTop: '5px', flexShrink: 0,
          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
        }}>
          {card.title}
        </p>
      </div>
    </div>
  );
});

/* ── Card Modal ── */
function CardModal({ card, onClose, isFavorited, onToggleFavorite }) {
  const cardRef = React.useRef(null);

  const handleMouseMove = (e) => {
    if (!cardRef.current) return;
    const rect = cardRef.current.getBoundingClientRect();
    const rx = (e.clientY - rect.top  - rect.height / 2) / 15;
    const ry = (rect.left + rect.width / 2 - e.clientX) / 15;
    cardRef.current.style.transform = `perspective(1000px) rotateX(${rx}deg) rotateY(${ry}deg)`;
  };
  const handleMouseEnter = () => {
    if (cardRef.current) cardRef.current.style.transition = 'none';
  };
  const handleMouseLeave = () => {
    if (cardRef.current) {
      cardRef.current.style.transition = 'transform 0.5s ease-out';
      cardRef.current.style.transform  = 'perspective(1000px) rotateX(0deg) rotateY(0deg)';
    }
  };

  return (
    <div
      style={{
        position: 'fixed', inset: 0, zIndex: 50,
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        background: 'rgba(0,0,0,0.88)', backdropFilter: 'blur(10px)',
        padding: '16px',
      }}
      onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}
    >
      {/* Close — fixed position, always visible */}
      <button
        onClick={onClose}
        style={{
          position: 'fixed', top: '14px', right: '14px', zIndex: 60,
          width: '38px', height: '38px',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          borderRadius: '50%', border: '1px solid rgba(255,255,255,0.18)',
          background: 'rgba(28,28,28,0.85)', backdropFilter: 'blur(8px)',
          color: 'white', cursor: 'pointer',
        }}
      >
        <XIcon />
      </button>

      {/* Scrollable inner */}
      <div style={{
        width: '100%', maxWidth: '340px',
        maxHeight: 'calc(100svh - 80px)',
        overflowY: 'auto', overscrollBehavior: 'contain',
        borderRadius: '18px',
      }}>
        <div
          ref={cardRef}
          style={{
            borderRadius: '18px', background: '#1F2121', padding: '14px',
            cursor: 'pointer', transformStyle: 'preserve-3d',
            boxShadow: '0 24px 64px rgba(0,0,0,0.75)',
            transition: 'transform 0.3s ease',
          }}
          onMouseMove={handleMouseMove}
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
        >
          <div style={{ position: 'relative', width: '100%', aspectRatio: '3/4', marginBottom: '12px' }}>
            <img
              loading="lazy" src={card.imageUrl} alt={card.alt}
              style={{
                position: 'absolute', inset: 0, width: '100%', height: '100%',
                borderRadius: '12px', objectFit: 'cover', background: '#000',
              }}
            />
          </div>
          <h3 style={{
            color: 'white', fontSize: '15px', fontWeight: 600,
            textAlign: 'center', margin: '0 0 12px',
            fontFamily: 'Sora, sans-serif',
          }}>
            {card.title}
          </h3>
          <div style={{ display: 'flex', gap: '8px' }}>
            <button style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              gap: '6px', height: '42px', flex: 1,
              borderRadius: '10px', border: 'none', cursor: 'pointer',
              background: '#31b8c6', color: 'black', fontWeight: 600, fontSize: '14px',
            }}>
              <DownloadIcon /><span>Descargar</span>
            </button>
            <button
              onClick={onToggleFavorite}
              style={{
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                width: '42px', height: '42px', flexShrink: 0,
                borderRadius: '10px', border: 'none', cursor: 'pointer',
                background: '#31b8c6', color: 'black',
              }}
            >
              <HeartIcon filled={isFavorited} />
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

/* ── Main Component ── */
function StellarCardGallery() {
  const [selectedCard, setSelectedCard] = React.useState(null);
  const [isFavorited,  setIsFavorited]  = React.useState(false);
  const [dims, setDims] = React.useState(getResponsiveDims);

  const dimsRef = React.useRef(dims);
  React.useLayoutEffect(() => { dimsRef.current = dims; }, [dims]);

  React.useEffect(() => {
    let timer;
    const onResize = () => {
      clearTimeout(timer);
      timer = setTimeout(() => {
        const next = getResponsiveDims();
        dimsRef.current = next;
        setDims(next);
      }, 80);
    };
    window.addEventListener('resize', onResize);
    window.addEventListener('orientationchange', onResize);
    return () => {
      window.removeEventListener('resize', onResize);
      window.removeEventListener('orientationchange', onResize);
      clearTimeout(timer);
    };
  }, []);

  const cards = [
    { id: '1',  imageUrl: 'https://i.ibb.co/4ZWcP129/1.png',    alt: 'Elegant Invitation', title: 'Elegant Invitation' },
    { id: '2',  imageUrl: 'https://i.ibb.co/TMbhBRcL/2.png',    alt: 'Modern Design',      title: 'Modern Design' },
    { id: '3',  imageUrl: 'https://i.ibb.co/spXBFdSm/3.png',    alt: 'Vintage Style',      title: 'Vintage Style' },
    { id: '4',  imageUrl: 'https://i.ibb.co/N2TCN0bC/4.png',    alt: 'Minimalist',         title: 'Minimalist' },
    { id: '5',  imageUrl: 'https://i.ibb.co/jZkh6q1M/5.png',    alt: 'Floral Design',      title: 'Floral Design' },
    { id: '6',  imageUrl: 'https://i.ibb.co/6cc7mksr/6.png',    alt: 'Geometric',          title: 'Geometric' },
    { id: '7',  imageUrl: 'https://i.ibb.co/bjV35jNQ/7.png',    alt: 'Luxury Gold',        title: 'Luxury Gold' },
    { id: '8',  imageUrl: 'https://i.ibb.co/PZ7WLs7g/8.png',    alt: 'Rustic Style',       title: 'Rustic Style' },
    { id: '9',  imageUrl: 'https://i.ibb.co/qLR5bQRM/9.png',    alt: 'Dark Modern',        title: 'Dark Modern' },
    { id: '10', imageUrl: 'https://i.ibb.co/PdNhw3K/10.png',    alt: 'Colorful Party',     title: 'Colorful Party' },
    { id: '11', imageUrl: 'https://i.ibb.co/zWpN1nqJ/11.png',   alt: 'Geometric',          title: 'Geometric' },
    { id: '12', imageUrl: 'https://i.ibb.co/fVYnCXgR/12.png',   alt: 'Luxury Gold',        title: 'Luxury Gold' },
    { id: '13', imageUrl: 'https://i.ibb.co/1G6jZWcZ/13.png',   alt: 'Rustic Style',       title: 'Rustic Style' },
    { id: '14', imageUrl: 'https://i.ibb.co/xKG7m905/14.png',   alt: 'Dark Modern',        title: 'Dark Modern' },
    { id: '15', imageUrl: 'https://i.ibb.co/7dJzR3xK/15.png',   alt: 'Colorful Party',     title: 'Colorful Party' },
    { id: '16', imageUrl: 'https://i.ibb.co/NdJ1csXB/16.png',   alt: 'Elegant Script',     title: 'Elegant Script' },
    { id: '17', imageUrl: 'https://i.ibb.co/8L2Sdt5Q/17.png',   alt: 'Watercolor Art',     title: 'Watercolor Art' },
    { id: '18', imageUrl: 'https://i.ibb.co/mC1zxJYq/18.png',   alt: 'Botanical',          title: 'Botanical' },
    { id: '19', imageUrl: 'https://i.ibb.co/wryzsKs4/20.png',   alt: 'Art Deco',           title: 'Art Deco' },
    { id: '20', imageUrl: 'https://i.ibb.co/1fvnxL3L/19.png',   alt: 'Marble Luxury',      title: 'Marble Luxury' },
  ];

  /* Golden-ratio sphere positions (unit sphere × radius layers) */
  const cardPositions = React.useMemo(() => {
    const n = cards.length, phi = (1 + Math.sqrt(5)) / 2;
    return cards.map((_, i) => {
      const y = 1 - (i / (n - 1)) * 2;
      const r = Math.sqrt(Math.max(0, 1 - y * y));
      const theta = (2 * Math.PI * i) / phi;
      const R = 12 + (i % 3) * 4;          // radii: 12, 14, 16
      return { x: Math.cos(theta) * r * R, y: y * R, z: Math.sin(theta) * r * R };
    });
  }, []);

  /* Refs — all updated directly in rAF to avoid 60fps React re-renders */
  const cardRefs     = React.useRef([]);
  const rotRef       = React.useRef({ x: getResponsiveDims().rotX0, y: 0 });
  const isDragging   = React.useRef(false);
  const inputRef     = React.useRef({ x: 0, y: 0 });
  const dragDistRef  = React.useRef(0);
  const rafRef       = React.useRef(null);
  const dragLayerRef = React.useRef(null);

  /* Position update — reads dimsRef so it never stales */
  const updatePositions = React.useCallback(() => {
    const { CARD_W, CARD_H, SCALE, FOV } = dimsRef.current;
    const { x: rotX, y: rotY } = rotRef.current;
    const cosX = Math.cos(rotX * Math.PI / 180), sinX = Math.sin(rotX * Math.PI / 180);
    const cosY = Math.cos(rotY * Math.PI / 180), sinY = Math.sin(rotY * Math.PI / 180);

    const projected = cardPositions.map((pos, i) => {
      /* Rotate around X then Y */
      const y1 = pos.y * cosX - pos.z * sinX;
      const z1 = pos.y * sinX + pos.z * cosX;
      const x2 = pos.x * cosY + z1 * sinY;
      const z2 = -pos.x * sinY + z1 * cosY;
      /* Perspective projection */
      const depth = z2 * SCALE;
      const p  = FOV / (FOV + depth);   // scale: >1 = closer, <1 = farther
      const sx = x2 * SCALE * p;
      const sy = -y1 * SCALE * p;       // negate Y: 3D up = CSS up
      return { sx, sy, p, depth, i };
    });

    /* Sort back-to-front so closer cards sit on top */
    projected.sort((a, b) => a.depth - b.depth);

    projected.forEach(({ sx, sy, p, i }, zOrder) => {
      const el = cardRefs.current[i];
      if (!el) return;
      /* transformOrigin is at card center, so translate by half-card before scale */
      el.style.transform = `translate(${sx - CARD_W / 2}px, ${sy - CARD_H / 2}px) scale(${p})`;
      el.style.zIndex    = zOrder + 1;
    });
  }, [cardPositions]);

  /* Auto-rotate rAF loop */
  React.useEffect(() => {
    let last = 0;
    const tick = (t) => {
      if (!isDragging.current) {
        rotRef.current.y += Math.min(t - last, 50) * 0.018;
      }
      last = t;
      updatePositions();
      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(rafRef.current);
  }, [updatePositions]);

  /* Native touch — needs { passive: false } to call preventDefault (blocks page scroll) */
  React.useEffect(() => {
    const el = dragLayerRef.current;
    if (!el) return;

    const onTouchStart = (e) => {
      if (e.touches.length > 1) return;
      isDragging.current  = true;
      dragDistRef.current = 0;
      inputRef.current    = { x: e.touches[0].clientX, y: e.touches[0].clientY };
    };
    const onTouchMove = (e) => {
      if (!isDragging.current || e.touches.length > 1) return;
      e.preventDefault();
      const dx = e.touches[0].clientX - inputRef.current.x;
      const dy = e.touches[0].clientY - inputRef.current.y;
      dragDistRef.current += Math.sqrt(dx * dx + dy * dy);
      rotRef.current.y += dx * 0.5;
      rotRef.current.x  = Math.max(-80, Math.min(80, rotRef.current.x - dy * 0.35));
      inputRef.current  = { x: e.touches[0].clientX, y: e.touches[0].clientY };
    };
    const onTouchEnd = () => { isDragging.current = false; };

    el.addEventListener('touchstart', onTouchStart, { passive: true });
    el.addEventListener('touchmove',  onTouchMove,  { passive: false });
    el.addEventListener('touchend',   onTouchEnd,   { passive: true });
    return () => {
      el.removeEventListener('touchstart', onTouchStart);
      el.removeEventListener('touchmove',  onTouchMove);
      el.removeEventListener('touchend',   onTouchEnd);
    };
  }, []);

  /* Mouse controls (desktop) */
  const onMouseDown = (e) => {
    isDragging.current  = true;
    dragDistRef.current = 0;
    inputRef.current    = { x: e.clientX, y: e.clientY };
  };
  const onMouseMove = (e) => {
    if (!isDragging.current) return;
    const dx = e.clientX - inputRef.current.x, dy = e.clientY - inputRef.current.y;
    dragDistRef.current += Math.sqrt(dx * dx + dy * dy);
    rotRef.current.y += dx * 0.4;
    rotRef.current.x  = Math.max(-80, Math.min(80, rotRef.current.x - dy * 0.3));
    inputRef.current  = { x: e.clientX, y: e.clientY };
  };
  const stopDrag = () => { isDragging.current = false; };

  return (
    <div style={{ width: '100vw', height: '100dvh', position: 'relative', overflow: 'hidden', background: '#000' }}>

      <StarfieldBackground />

      {/* Interaction + card layer */}
      <div
        ref={dragLayerRef}
        style={{
          position: 'absolute', inset: 0, zIndex: 10,
          userSelect: 'none', touchAction: 'none', cursor: 'grab',
        }}
        onMouseDown={onMouseDown}
        onMouseMove={onMouseMove}
        onMouseUp={stopDrag}
        onMouseLeave={stopDrag}
      >
        {/* Galaxy origin — shifted down on mobile to clear nav + title overlay */}
        <div style={{ position: 'absolute', left: '50%', top: dims.originY }}>
          {cards.map((card, i) => (
            <FloatingCard
              key={card.id}
              card={card}
              ref={(el) => { cardRefs.current[i] = el; }}
              onSelect={setSelectedCard}
              dragDistRef={dragDistRef}
              cardW={dims.CARD_W}
              cardH={dims.CARD_H}
            />
          ))}
        </div>
      </div>

      {/* HUD hint */}
      <div style={{
        position: 'absolute',
        bottom: 'max(16px, env(safe-area-inset-bottom, 16px))',
        left: 0, right: 0, zIndex: 20,
        textAlign: 'center', pointerEvents: 'none',
        color: 'rgba(255,255,255,0.3)',
        fontSize: dims.mobile ? '11px' : '12px',
        letterSpacing: '0.06em', fontFamily: 'Inter, sans-serif',
      }}>
        {dims.mobile
          ? 'Arrastra para rotar · Toca para ver'
          : 'Arrastra para rotar · Click en una tarjeta para verla'}
      </div>

      {/* Modal */}
      {selectedCard && (
        <CardModal
          card={selectedCard}
          onClose={() => { setSelectedCard(null); setIsFavorited(false); }}
          isFavorited={isFavorited}
          onToggleFavorite={() => setIsFavorited(v => !v)}
        />
      )}
    </div>
  );
}
