// HeroStage — immersive interactive hero. Replaces the old <Hero>.
//
// Interaction:
//  - Aurora background tracks cursor.
//  - Central hub tilts (3D) toward cursor.
//  - Five model planets orbit, parallax-shift toward cursor, draw faint lines back to the hub.
//  - Headline cycles through rotating words ("в одном месте" / "в одном чате" / "в одной подписке").
//  - Ticker scrolls capabilities forever.
//  - Custom cursor follower morphs when near a planet.

const { useEffect, useRef, useState, useMemo } = React;

const ROTATING_WORDS = [
  'в одном месте',
  'в одном чате',
  'в одной подписке',
  'в одной вкладке',
];

const TICKER_ITEMS = [
  { tx: 'Длинные тексты', c: '#e89070' },
  { tx: 'Код и алгоритмы', c: '#7e96ff' },
  { tx: 'Анализ изображений', c: '#7c8fff' },
  { tx: 'Идеи и брейншторм', c: '#3ec4a3' },
  { tx: 'Realtime-поиск', c: '#dde1ea' },
  { tx: 'Перевод и копирайт', c: '#e89070' },
  { tx: 'Математика и логика', c: '#7e96ff' },
  { tx: 'Учёба и конспекты', c: '#3ec4a3' },
  { tx: 'Креатив и стиль', c: '#a06bff' },
  { tx: 'Скоро: изображения и видео', c: '#4be3d0' },
];

// Use an existing constant in module scope across re-renders.
const planetSeeds = (models) => {
  // Spread around the orbit; bigger models on the visible hemisphere.
  const N = models.length;
  return models.map((m, i) => {
    // angle: place evenly with a slight rotation
    const angle = (i / N) * Math.PI * 2 - Math.PI / 2 + 0.2;
    return {
      id: m.id,
      angle,
      // radius is % of orbit container's half-size.
      radius: 90,
      // each planet bobs at different freq for organic motion
      freq: 0.25 + (i % 3) * 0.12,
      phase: i * 1.3,
      depth: 0.6 + (i % 3) * 0.15,
    };
  });
};

const HeroStage = ({ heroCTA = 'Попробовать' }) => {
  const stageRef = useRef(null);
  const hubRef = useRef(null);
  const cursorRef = useRef(null);
  const linesRef = useRef(null);
  const orbitRef = useRef(null);
  const planetRefs = useRef({});
  const [wordIdx, setWordIdx] = useState(0);
  const [overPlanet, setOverPlanet] = useState(false);

  const models = useMemo(() => window.PROVIDER_REPS, []);
  const seeds = useMemo(() => planetSeeds(models), [models]);

  // Rotate the word
  useEffect(() => {
    const t = setInterval(() => {
      setWordIdx(prev => (prev + 1) % ROTATING_WORDS.length);
    }, 2800);
    return () => clearInterval(t);
  }, []);

  // Cursor tracking + animation loop
  useEffect(() => {
    const stage = stageRef.current;
    const orbit = orbitRef.current;
    if (!stage || !orbit) return;

    // Normalized cursor position relative to stage center: -1..1
    let nx = 0, ny = 0;        // target normalized
    let cx = 0, cy = 0;        // smoothed
    let mx = 0, my = 0;        // raw pointer in stage px
    let orbitMx = 0, orbitMy = 0; // pointer in orbit px
    let pointerInStage = false;
    let startTime = performance.now();
    let raf;

    const onMove = (e) => {
      const sRect = stage.getBoundingClientRect();
      mx = e.clientX - sRect.left;
      my = e.clientY - sRect.top;
      pointerInStage = mx >= 0 && my >= 0 && mx <= sRect.width && my <= sRect.height;

      // Normalized: -1 (left/top) ... 1 (right/bottom)
      nx = ((mx / sRect.width) - 0.5) * 2;
      ny = ((my / sRect.height) - 0.5) * 2;

      const oRect = orbit.getBoundingClientRect();
      orbitMx = e.clientX - oRect.left;
      orbitMy = e.clientY - oRect.top;

      // CSS vars for aurora + cursor follower
      stage.style.setProperty('--mx', `${(mx / sRect.width) * 100}%`);
      stage.style.setProperty('--my', `${(my / sRect.height) * 100}%`);

      // Update cursor follower position
      if (cursorRef.current) {
        cursorRef.current.style.left = `${mx}px`;
        cursorRef.current.style.top = `${my}px`;
      }
    };

    const onEnter = () => {
      pointerInStage = true;
      if (cursorRef.current) cursorRef.current.classList.add('in');
    };
    const onLeave = () => {
      pointerInStage = false;
      nx = 0; ny = 0;
      if (cursorRef.current) cursorRef.current.classList.remove('in');
    };

    stage.addEventListener('mousemove', onMove);
    stage.addEventListener('mouseenter', onEnter);
    stage.addEventListener('mouseleave', onLeave);

    const tick = (t) => {
      const elapsed = (t - startTime) / 1000;

      // Smooth cursor normalized values
      cx += (nx - cx) * 0.08;
      cy += (ny - cy) * 0.08;

      // Stage-level parallax
      stage.style.setProperty('--px', cx.toFixed(3));
      stage.style.setProperty('--py', cy.toFixed(3));

      // Hub 3D tilt
      const hub = hubRef.current;
      if (hub) {
        const tiltX = -cy * 14;
        const tiltY = cx * 14;
        hub.style.transform = `perspective(800px) rotateX(${tiltX}deg) rotateY(${tiltY}deg)`;
      }

      // Animate planets
      const oRect = orbit.getBoundingClientRect();
      const orbitW = oRect.width;
      const orbitH = oRect.height;
      const centerX = orbitW / 2;
      const centerY = orbitH / 2;

      const lineSegs = [];
      let anyOverPlanet = false;

      seeds.forEach((p, i) => {
        const node = planetRefs.current[p.id];
        if (!node) return;

        // Shared rotation — all planets drift together so spacing stays constant.
        const sharedRot = elapsed * 0.05;
        const angle = p.angle + sharedRot;
        const r = (p.radius / 100) * Math.min(orbitW, orbitH) / 2;
        // Small per-planet bob along the radial direction only (no tangential wobble → no collisions)
        const radialBob = Math.sin(elapsed * p.freq + p.phase) * 6;
        const baseX = Math.cos(angle) * (r + radialBob);
        const baseY = Math.sin(angle) * (r + radialBob);

        // Magnetic pull toward cursor (when pointer is in orbit area)
        let pullX = 0, pullY = 0, isNear = false;
        const planetX = centerX + baseX;
        const planetY = centerY + baseY;
        if (pointerInStage) {
          const dx = orbitMx - planetX;
          const dy = orbitMy - planetY;
          const dist = Math.sqrt(dx*dx + dy*dy);
          const range = 140;
          if (dist < range) {
            const force = (1 - dist / range);
            // gentler pull, capped so they can't be dragged into the hub
            pullX = dx * 0.12 * force;
            pullY = dy * 0.12 * force;
            isNear = dist < 70;
          }
        }
        if (isNear) anyOverPlanet = true;

        let tx = baseX + pullX;
        let ty = baseY + pullY;

        // Clamp: keep planets at least minR from center so they never enter the hub.
        const minR = Math.min(orbitW, orbitH) * 0.40;
        const distFromCenter = Math.sqrt(tx*tx + ty*ty);
        if (distFromCenter < minR) {
          const k = minR / Math.max(distFromCenter, 0.001);
          tx *= k;
          ty *= k;
        }

        node.style.setProperty('--tx', `${tx.toFixed(2)}px`);
        node.style.setProperty('--ty', `${ty.toFixed(2)}px`);

        // Track segment endpoints for line drawing (planet center → hub center)
        // Use the actual clamped tx/ty (not pre-clamp planetX/Y).
        lineSegs.push({
          x1: centerX, y1: centerY,
          x2: centerX + tx, y2: centerY + ty,
          near: isNear,
          color: models[i]?.markColor || '#5b8cff',
        });
      });

      // Update SVG lines
      const linesEl = linesRef.current;
      if (linesEl) {
        // Build/cache children once
        let children = linesEl.children;
        while (children.length < seeds.length) {
          const ln = document.createElementNS('http://www.w3.org/2000/svg', 'line');
          ln.setAttribute('stroke-linecap', 'round');
          linesEl.appendChild(ln);
          children = linesEl.children;
        }
        lineSegs.forEach((s, i) => {
          const ln = children[i];
          ln.setAttribute('x1', s.x1);
          ln.setAttribute('y1', s.y1);
          ln.setAttribute('x2', s.x2);
          ln.setAttribute('y2', s.y2);
          ln.setAttribute('stroke', s.color);
          ln.setAttribute('stroke-width', s.near ? '1.4' : '0.6');
          ln.setAttribute('opacity', s.near ? '0.9' : '0.25');
          ln.setAttribute('stroke-dasharray', s.near ? '0' : '4 6');
        });
      }

      // Cursor follower morph
      if (cursorRef.current) {
        cursorRef.current.classList.toggle('over-planet', anyOverPlanet);
      }
      setOverPlanet(anyOverPlanet);

      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(raf);
      stage.removeEventListener('mousemove', onMove);
      stage.removeEventListener('mouseenter', onEnter);
      stage.removeEventListener('mouseleave', onLeave);
    };
  }, []);

  // Reveal-on-scroll observer (lightweight)
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    if (!els.length || !('IntersectionObserver' in window)) {
      els.forEach(el => el.classList.add('in'));
      return;
    }
    const io = new IntersectionObserver((entries) => {
      entries.forEach(en => {
        if (en.isIntersecting) {
          en.target.classList.add('in');
          io.unobserve(en.target);
        }
      });
    }, { threshold: 0.12 });
    els.forEach(el => io.observe(el));
    return () => io.disconnect();
  }, []);

  return (
    <section className="stage" ref={stageRef} id="hero">
      <div className="stage-aurora"></div>
      <div className="stage-ring outer"></div>
      <div className="stage-ring"></div>
      <div className="stage-grain"></div>

      {/* Cursor follower */}
      <div className="stage-cursor" ref={cursorRef}></div>

      <div className="stage-content">
        {/* LEFT: text */}
        <div className="stage-text">
          <div className="stage-eyebrow">
            <span className="live">v1.0 · live</span>
            <span>Все модели в одной подписке от $5</span>
          </div>

          <h1 className="stage-headline">
            <span className="l1 word">Все нейросети</span>
            <span className="l2">
              <span className="swap">
                {ROTATING_WORDS.map((w, i) => (
                  <span
                    key={i}
                    className={'swap-word ' + (i === wordIdx ? 'in' : 'out')}
                    aria-hidden={i !== wordIdx}
                  >{w}</span>
                ))}
              </span>
            </span>
          </h1>

          <p className="stage-sub">
            GPT-5.5, Claude Opus 4.7, Gemini 3.1, Grok 4.3, DeepSeek V4 — 17 моделей в одном чате.
            Один интерфейс, одна подписка.
          </p>

          <div className="stage-cta">
            <a className="stage-cta-primary" href="chat.html">
              {heroCTA}
              <Icon name="arrow-right" size={16} stroke={2}/>
            </a>
            <button className="stage-cta-ghost">
              <span className="pl"><Icon name="play" size={10}/></span>
              Смотреть демо
            </button>
          </div>

          <div className="stage-meta">
            <div className="stage-meta-item">
              <span className="px"><Icon name="check" size={9}/></span> 5+ моделей
            </div>
            <div className="stage-meta-item">
              <span className="px"><Icon name="check" size={9}/></span> Без VPN
            </div>
            <div className="stage-meta-item">
              <span className="px"><Icon name="check" size={9}/></span> $5/мес — отмена в 1 клик
            </div>
          </div>
        </div>

        {/* RIGHT: constellation */}
        <div className="stage-orbit" ref={orbitRef}>
          <div className="stage-orbit-ring"></div>
          <div className="stage-orbit-ring inner"></div>
          <svg
            className="lines"
            preserveAspectRatio="none"
            viewBox="0 0 100 100"
            style={{ width: '100%', height: '100%' }}
            ref={(el) => {
              if (el) {
                // Replace viewBox so coords are in PX — easier to wire from JS.
                el.setAttribute('viewBox', `0 0 ${el.clientWidth} ${el.clientHeight}`);
                linesRef.current = el;
              }
            }}
          />

          {/* Hub */}
          <div className="stage-hub">
            <div className="stage-hub-pulse"></div>
            <div className="stage-hub-pulse"></div>
            <div className="stage-hub-pulse"></div>
            <div className="stage-hub-core" ref={hubRef}>
              <span className="lbl">Nepl AI Hub</span>
              <span className="ttl">Все нейросети<br/>в одном чате</span>
            </div>
          </div>

          {/* Planets */}
          {seeds.map((p, i) => {
            const m = models[i];
            if (!m) return null;
            // Compute initial position based on a 600px assumed orbit (refined by JS rAF after mount)
            const assumedHalf = 300; // half of max-width 600
            const initialTx = Math.cos(p.angle) * (p.radius / 100) * assumedHalf;
            const initialTy = Math.sin(p.angle) * (p.radius / 100) * assumedHalf;
            return (
              <div
                key={p.id}
                className="stage-planet"
                ref={(el) => { if (el) planetRefs.current[p.id] = el; }}
                style={{
                  '--depth': p.depth,
                  '--tx': `${initialTx.toFixed(2)}px`,
                  '--ty': `${initialTy.toFixed(2)}px`,
                }}
              >
                <div className="stage-planet-inner">
                  <div className="stage-planet-card">
                    <span className="badge"><window.ModelMark model={m} size={18}/></span>
                    <span className="nm">{m.family}</span>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      {/* Scroll cue */}
      <div className="stage-scroll-cue">
        <span>scroll</span>
        <div className="bar"></div>
      </div>
    </section>
  );
};

// Ticker strip below hero
const StageTicker = () => (
  <div className="stage-ticker" aria-hidden="true">
    <div className="stage-ticker-track">
      {[...TICKER_ITEMS, ...TICKER_ITEMS].map((it, i) => (
        <span key={i} className="stage-ticker-item">
          <span className="dotc" style={{ background: it.c, boxShadow: `0 0 8px ${it.c}` }}></span>
          {it.tx}
        </span>
      ))}
    </div>
  </div>
);

window.HeroStage = HeroStage;
window.StageTicker = StageTicker;
