/* global React, ReactDOM */

/* ============================================================
   FUNNEL — the signature D-01 visual
   Orbital layout: 5 stages on an arc with curves back to a
   central "your context" anchor, visualizing the shared-context
   promise of the product (not a flat pipeline).
   ============================================================ */

const STAGES = [
  {
    n: "01",
    name: "Company Intel",
    verb: "Research",
    micro: ["Brief the target", "Cards & follow-ups"],
    soon: false,
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <circle cx="11" cy="11" r="6"></circle>
        <path d="M15.5 15.5 20 20"></path>
        <path d="M8 11h6 M11 8v6" opacity=".4"></path>
      </svg>
    )
  },
  {
    n: "02",
    name: "Resume Review",
    verb: "Apply",
    micro: ["Tailor for fit", "Score & rewrite"],
    soon: false,
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <path d="M7 3h8l4 4v14H7z"></path>
        <path d="M15 3v4h4"></path>
        <path d="M10 12h6 M10 15h6 M10 18h4" opacity=".5"></path>
      </svg>
    )
  },
  {
    n: "03",
    name: "First Touch",
    verb: "Connect",
    micro: ["Reach the team", "Get a reply"],
    soon: true,
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <path d="M4 7l8 6 8-6"></path>
        <rect x="4" y="6" width="16" height="13" rx="2"></rect>
      </svg>
    )
  },
  {
    n: "04",
    name: "Interview Prep",
    verb: "Prep",
    micro: ["Practice rounds", "Graded · re-answer"],
    soon: false,
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <path d="M4 6a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H9l-4 3v-3H6a2 2 0 0 1-2-2z"></path>
        <path d="M11 14v1a2 2 0 0 0 2 2h4l3 3v-3h0a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2h-2" opacity=".55"></path>
      </svg>
    )
  },
  {
    n: "05",
    name: "Last Touch",
    verb: "Close",
    micro: ["Stay top of mind", "Through to offer"],
    soon: true,
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <path d="M4 12h12 M12 8l4 4-4 4"></path>
        <circle cx="19" cy="12" r="2.4"></circle>
      </svg>
    )
  }
];

/* Compute orbital positions: an arc from ~210° to ~330° (top half),
   stage 1 left → stage 5 right. Center anchor sits below the arc. */
function arcPos(i, n, radius, cx, cy) {
  const startDeg = 200;
  const endDeg = 340;
  const t = i / (n - 1);
  const deg = startDeg + t * (endDeg - startDeg);
  const rad = (deg * Math.PI) / 180;
  return { x: cx + Math.cos(rad) * radius, y: cy + Math.sin(rad) * radius };
}

/* Compute pill positions: evenly spaced HORIZONTALLY across the canvas,
   with a gentle symmetric arch in Y so the middle pill sits highest.
   This guarantees uniform spacing and predictable line geometry. */
function pillPos(i, n, W, archTop, archBottom) {
  // Even horizontal spacing with padding from the edges.
  const padX = W * 0.10;
  const t = n === 1 ? 0.5 : i / (n - 1);
  const x = padX + t * (W - 2 * padX);
  // Symmetric arch: y = top + (bottom - top) * (1 - cos(theta))/...
  // simpler: parabolic in (t-0.5) so middle is highest.
  const arch = 4 * Math.pow(t - 0.5, 2); // 1 at edges, 0 in middle
  const y = archTop + (archBottom - archTop) * arch;
  return { x, y };
}

function Funnel({ active, hover: hoverProp, onHover, onLeave, onPick }) {
  // Allow legacy callers (no hover wiring): fall back to local hover state.
  const [localHover, setLocalHover] = React.useState(null);
  const hover = hoverProp !== undefined ? hoverProp : localHover;
  const focus = hover !== null ? hover : active;
  const handleEnter = (i) => { onHover ? onHover(i) : setLocalHover(i); };
  const handleLeaveNode = () => { onLeave ? onLeave() : setLocalHover(null); };
  const W = 1100, H = 560;
  const CX = W / 2;
  const ANCHOR_Y = 410;        // y of the anchor center
  const ANCHOR_R = 94;         // anchor circle radius (was 78, +20%)
  const ARCH_TOP = 130;        // y of the middle (highest) pill
  const ARCH_BOTTOM = 230;     // y of the outer pills

  return (
    <div className="funnel" role="figure" aria-label="Five coordinated tools that share context">
      <svg className="funnel-svg" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="xMidYMid meet">
        <defs>
          <radialGradient id="anchorGlow" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="rgba(15,118,110,.30)"></stop>
            <stop offset="100%" stopColor="rgba(15,118,110,0)"></stop>
          </radialGradient>
          <linearGradient id="connStroke" gradientUnits="userSpaceOnUse" x1="0" y1="130" x2="0" y2="410">
            <stop offset="0%" stopColor="rgba(15,118,110,.65)"></stop>
            <stop offset="100%" stopColor="rgba(15,118,110,.18)"></stop>
          </linearGradient>
          <linearGradient id="connStrokeActive" gradientUnits="userSpaceOnUse" x1="0" y1="130" x2="0" y2="410">
            <stop offset="0%" stopColor="rgba(245,158,11,.95)"></stop>
            <stop offset="100%" stopColor="rgba(245,158,11,.35)"></stop>
          </linearGradient>
        </defs>

        {/* anchor glow */}
        <circle cx={CX} cy={ANCHOR_Y} r="170" fill="url(#anchorGlow)" />

        {/* connection lines: pill bottom → anchor edge. */}
        {STAGES.map((s, i) => {
          const p = pillPos(i, STAGES.length, W, ARCH_TOP, ARCH_BOTTOM);
          const isActive = focus === i;
          // Per-pill vertical offset so the line endpoint hugs the pill bottom
          // for each row of the arch.
          const PILL_OFFSETS = [60, 60, 30, 60, 60];
          const PILL_OFFSET = PILL_OFFSETS[i] ?? 30;
          const sx = p.x;
          const sy = p.y + PILL_OFFSET;
          // End on the anchor circle, along the line from anchor center to pill.
          const dx = sx - CX;
          const dy = sy - ANCHOR_Y;
          const dist = Math.hypot(dx, dy) || 1;
          const ux = dx / dist;
          const uy = dy / dist;
          const tx = CX + ux * ANCHOR_R;
          const ty = ANCHOR_Y + uy * ANCHOR_R;
          // cubic with vertical-leaning control points for a nice bell curve
          const c1x = sx;
          const c1y = sy + (ty - sy) * 0.6;
          const c2x = tx;
          const c2y = ty - (ty - sy) * 0.25;
          return (
            <path
              key={`conn-${i}`}
              d={`M ${sx} ${sy} C ${c1x} ${c1y} ${c2x} ${c2y} ${tx} ${ty}`}
              fill="none"
              stroke={isActive ? "url(#connStrokeActive)" : "url(#connStroke)"}
              strokeWidth={isActive ? 2 : 1}
              strokeOpacity={isActive ? 1 : 0.6}
              strokeLinecap="round"
              strokeDasharray={s.soon ? "5 6" : "0"}
              className={`funnel-conn${isActive ? " is-active" : ""}${s.soon ? " is-soon" : ""}`}
            />
          );
        })}

        {/* the active stage label — swaps as auto-cycle advances */}
        <g transform={`translate(${CX} ${ANCHOR_Y})`} key={focus} className="funnel-anchor-text">
          <circle r={ANCHOR_R} fill="var(--surface)" stroke="var(--border)" strokeWidth="1" />
          <circle r={ANCHOR_R} fill="none" stroke="rgba(15,118,110,.35)" strokeWidth="1" strokeDasharray="3 4" />
          <text x="0" y="-26" textAnchor="middle" fontSize="10" letterSpacing="0.16em" fill="var(--ink-3)" fontWeight="700">{STAGES[focus].name.toUpperCase()}</text>
          <text x="0" y="2" textAnchor="middle" fontSize="16" fill="var(--ink)" fontWeight="600" letterSpacing="-0.01em">{STAGES[focus].micro[0]}</text>
          <text x="0" y="26" textAnchor="middle" fontSize="16" fill="var(--ink)" fontWeight="600" letterSpacing="-0.01em">{STAGES[focus].micro[1]}</text>
        </g>
      </svg>

      {/* Stage nodes as HTML overlay for crisp typography + a11y */}
      <div className="funnel-nodes" aria-hidden="false">
        {STAGES.map((s, i) => {
          const p = pillPos(i, STAGES.length, W, ARCH_TOP, ARCH_BOTTOM);
          const left = (p.x / W) * 100;
          const top = (p.y / H) * 100;
          const isActive = focus === i;
          return (
            <button
              key={s.name}
              className={`funnel-node${isActive ? " is-active" : ""}${s.soon ? " is-soon" : ""}`}
              style={{ left: `${left}%`, top: `${top}%` }}
              onMouseEnter={() => handleEnter(i)}
              onMouseLeave={handleLeaveNode}
              onFocus={() => handleEnter(i)}
              onBlur={handleLeaveNode}
              onClick={() => onPick && onPick(i)}
              aria-pressed={isActive}
            >
              <span className="funnel-node-icon">{s.icon}</span>
              <span className="funnel-node-meta">
                <span className="funnel-node-num">{s.n}</span>
                <span className="funnel-node-name">
                  {s.name}
                  {s.soon ? <span className="funnel-node-soon">soon</span> : null}
                </span>
              </span>
            </button>
          );
        })}
      </div>

      {/* Verb caption row, mapped 1:1 to stages */}
      <div className="funnel-verbs" aria-hidden="true">
        {STAGES.map((s, i) => (
          <span key={s.verb} className={`funnel-verb${focus === i ? " is-active" : ""}${s.soon ? " is-soon" : ""}`}>
            {s.verb}
          </span>
        ))}
      </div>
    </div>
  );
}

/* Mount on the element with id=funnel-root */
const AUTO_INTERVAL_MS = 5000;

(function mountFunnel() {
  const el = document.getElementById("funnel-root");
  if (!el) return;
  const root = ReactDOM.createRoot(el);
  function App() {
    const [active, setActive] = React.useState(0);
    const [hover, setHover] = React.useState(null);
    const focus = hover !== null ? hover : active;

    // Auto-cycle through stages; pause on hover.
    React.useEffect(() => {
      if (hover !== null) return;        // paused
      const id = setTimeout(() => {
        setActive((prev) => (prev + 1) % STAGES.length);
      }, AUTO_INTERVAL_MS);
      return () => clearTimeout(id);
    }, [active, hover]);

    // When the user stops hovering, resume cycling from the pill they were on.
    const handleHover = React.useCallback((i) => setHover(i), []);
    const handleLeave = React.useCallback(() => {
      setHover((h) => {
        if (h !== null) setActive(h);    // restart from where we paused
        return null;
      });
    }, []);

    // Allow click-to-pin: clicking a pill snaps active there and clears hover.
    const handlePick = React.useCallback((i) => {
      setHover(null);
      setActive(i);
    }, []);

    return (
      <Funnel
        active={active}
        hover={hover}
        onHover={handleHover}
        onLeave={handleLeave}
        onPick={handlePick}
      />
    );
  }
  root.render(<App />);
})();
