// ScrollRail — fixed vertical line on the right side of the viewport.
// Fills with coral as the user scrolls. Section ticks mark major anchors.
//
// Smoothness note: We listen to scroll directly (no React state) and animate
// the fill via ref + transform. React state-per-scroll causes jank because
// every scroll tick triggers a render+commit. The percentage label updates
// on rAF so it stays cheap.

const ScrollRail = () => {
  const fillRef = React.useRef(null);
  const pctRef = React.useRef(null);
  const dotsRef = React.useRef([]);
  const labelsRef = React.useRef([]);
  const [, force] = React.useReducer((x) => x + 1, 0);
  const sectionsRef = React.useRef(null);

  const sections = React.useMemo(() => [
    { id: 'hero', label: '00' },
    { id: 'annotation', label: '01' },
    { id: 'domains', label: '02' },
    { id: 'capability', label: '03' },
    { id: 'process', label: '04' },
    { id: 'cta', label: '05' },
  ], []);

  React.useEffect(() => {
    let raf = 0;
    let lastP = -1;
    let lastActive = -1;
    const tick = () => {
      raf = 0;
      const max = document.documentElement.scrollHeight - window.innerHeight;
      const p = max > 0 ? Math.max(0, Math.min(1, window.scrollY / max)) : 0;
      // Only paint when something changed
      if (Math.abs(p - lastP) > 0.0005) {
        lastP = p;
        if (fillRef.current) {
          // Use scaleY for compositor-only transform (no layout)
          fillRef.current.style.transform = `scaleY(${p})`;
        }
        if (pctRef.current) {
          pctRef.current.textContent = String(Math.round(p * 100)).padStart(2, '0') + '%';
        }
        // Update dots' passed state via class/style
        dotsRef.current.forEach((el, i) => {
          if (!el) return;
          const top = (i / (sections.length - 1));
          const passed = p >= top - 0.005;
          el.dataset.passed = passed ? '1' : '0';
        });
      }
      // Active section by viewport-mid line
      const mid = window.scrollY + window.innerHeight / 2;
      let a = 0;
      for (let i = 0; i < sections.length; i++) {
        const el = document.getElementById(sections[i].id);
        if (el) {
          const top = el.getBoundingClientRect().top + window.scrollY;
          if (top <= mid) a = i;
        }
      }
      if (a !== lastActive) {
        lastActive = a;
        dotsRef.current.forEach((el, i) => { if (el) el.dataset.active = i === a ? '1' : '0'; });
        labelsRef.current.forEach((el, i) => { if (el) el.dataset.active = i === a ? '1' : '0'; });
      }
    };
    const onScroll = () => {
      if (raf) return;
      raf = requestAnimationFrame(tick);
    };
    tick();
    window.addEventListener('scroll', onScroll, { passive: true });
    window.addEventListener('resize', onScroll);
    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener('scroll', onScroll);
      window.removeEventListener('resize', onScroll);
    };
  }, [sections]);

  // Smooth-scroll a section into view at the START of its pinned animation.
  // We can't rely on bare anchor links because PinnedScrub sections are
  // (scrubLength+1)*100vh tall and the visible pinned content starts at the
  // section top — anchor jump lands there, but we need the nav offset honored.
  const onJump = (e, id) => {
    e.preventDefault();
    window.__exScrollAndPlay(id);
  };

  return (
    <div className="ex-scroll-rail" style={{
      position: 'fixed',
      right: 22, top: '50%', transform: 'translateY(-50%)',
      height: 'min(440px, 60vh)',
      width: 28,
      zIndex: 40,
      pointerEvents: 'none',
      display: 'flex', flexDirection: 'column', alignItems: 'center',
    }}>
      <div ref={pctRef} style={{
        fontFamily: 'var(--ex-mono)', fontSize: 9,
        letterSpacing: '0.12em',
        color: 'var(--ex-mute)',
        marginBottom: 10,
        fontVariantNumeric: 'tabular-nums',
      }}>00%</div>

      <div style={{
        position: 'relative',
        flex: 1, width: 2,
        background: 'var(--ex-rule)',
        overflow: 'visible',
      }}>
        {/* Fill (transform: scaleY) */}
        <div ref={fillRef} style={{
          position: 'absolute', left: 0, right: 0, top: 0, bottom: 0,
          background: 'var(--ex-signal)',
          boxShadow: '0 0 8px var(--ex-signal-glow)',
          transform: 'scaleY(0)',
          transformOrigin: 'top',
          willChange: 'transform',
        }}/>

        {sections.map((s, i) => {
          const top = (i / (sections.length - 1)) * 100;
          return (
            <a key={s.id} href={`#${s.id}`}
               ref={(el) => { dotsRef.current[i] = el; }}
               data-passed="0" data-active="0"
               onClick={(e) => onJump(e, s.id)}
               className="rail-dot"
               style={{
                 position: 'absolute',
                 left: '50%',
                 top: `${top}%`,
                 transform: 'translate(-50%, -50%)',
                 borderRadius: '50%',
                 pointerEvents: 'auto',
                 cursor: 'pointer',
                 textDecoration: 'none',
               }}>
              <span ref={(el) => { labelsRef.current[i] = el; }}
                    data-active="0"
                    className="rail-label"
                    style={{
                      position: 'absolute',
                      right: 'calc(100% + 10px)',
                      top: '50%',
                      transform: 'translateY(-50%)',
                      fontFamily: 'var(--ex-mono)', fontSize: 9,
                      letterSpacing: '0.1em',
                      whiteSpace: 'nowrap',
                      pointerEvents: 'none',
                    }}>{s.label}</span>
            </a>
          );
        })}
      </div>

      <div style={{
        fontFamily: 'var(--ex-mono)', fontSize: 9,
        letterSpacing: '0.12em',
        color: 'var(--ex-mute)',
        marginTop: 10,
      }}>100</div>

      <style>{`
        .rail-dot { width: 6px; height: 6px;
                    background: var(--ex-cream);
                    border: 1px solid var(--ex-rule-strong);
                    box-shadow: 0 0 0 3px var(--ex-cream);
                    transition: width 0.18s, height 0.18s, background 0.18s, border-color 0.18s, box-shadow 0.18s; }
        .rail-dot[data-passed="1"] { background: var(--ex-signal); border-color: var(--ex-signal); }
        .rail-dot[data-active="1"] { width: 10px; height: 10px;
                    box-shadow: 0 0 0 4px rgba(240,238,233,0.9), 0 0 12px var(--ex-signal-glow); }
        .rail-label { color: var(--ex-mute); opacity: 0; transition: opacity 0.2s, color 0.2s; }
        .rail-label[data-active="1"] { color: var(--ex-signal); opacity: 1; }
      `}</style>
    </div>
  );
};

window.ScrollRail = ScrollRail;
