
const { useState, useEffect, useLayoutEffect, useRef, useCallback, Fragment } = React;

const FOREST = "#1b4d3e";

const ICONS = {
  book: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 4C9 4 7 2.5 4 2.5v12c3 0 5 1.5 5 1.5s2-1.5 5-1.5v-12c-3 0-5 1.5-5 1.5z"/>
      <line x1="9" y1="4" x2="9" y2="16"/>
    </svg>
  ),
  sparkle: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 1.5l1.8 5.7L17 9l-6.2 1.8L9 16.5l-1.8-5.7L1 9l6.2-1.8L9 1.5z"/>
    </svg>
  ),
  search: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="8" cy="8" r="4.5"/>
      <line x1="11.5" y1="11.5" x2="15.5" y2="15.5"/>
    </svg>
  ),
  lightbulb: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 2a5 5 0 0 1 3.5 8.5c-.5.5-.5 1-.5 1.5v.5H6V12c0-.5 0-1-.5-1.5A5 5 0 0 1 9 2z"/>
      <line x1="6.5" y1="14.5" x2="11.5" y2="14.5"/>
      <line x1="7.5" y1="16.5" x2="10.5" y2="16.5"/>
    </svg>
  ),
  flask: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M7 2v5L4 13a2 2 0 0 0 1.8 2.8h6.4A2 2 0 0 0 14 13l-3-6V2"/>
      <line x1="6.5" y1="2" x2="11.5" y2="2"/>
    </svg>
  ),
  trending: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <polyline points="2,13 6,8 10,11 16,4"/>
      <polyline points="12,4 16,4 16,8"/>
    </svg>
  ),
  "check-circle": (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <circle cx="9" cy="9" r="7"/>
      <polyline points="6,9 8,11 12,7"/>
    </svg>
  ),
  layers: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <polygon points="9,2 16,5.5 9,9 2,5.5"/>
      <polyline points="2,9 9,12.5 16,9"/>
      <polyline points="2,12.5 9,16 16,12.5"/>
    </svg>
  ),
  edit: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12.5 3l2.5 2.5-8 8-3.5 1 1-3.5 8-8z"/>
      <line x1="10.5" y1="5" x2="13" y2="7.5"/>
    </svg>
  ),
  warning: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M9 2L16.5 15H1.5L9 2z"/>
      <line x1="9" y1="8" x2="9" y2="11.5"/>
      <circle cx="9" cy="13.5" r="0.6" fill="currentColor" stroke="none"/>
    </svg>
  ),
  chat: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 3.5h12a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H6l-3 3V4.5a1 1 0 0 1 1-1z"/>
    </svg>
  ),
  scale: (
    <svg viewBox="0 0 18 18" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
      <line x1="9" y1="2" x2="9" y2="16"/>
      <path d="M5 6l-3 5h6L5 6z"/>
      <path d="M13 6l-3 5h6l-3-5z"/>
      <line x1="4" y1="16" x2="14" y2="16"/>
    </svg>
  ),
};

const SF =
  '"Avenir Next", -apple-system, BlinkMacSystemFont, "SF Pro Text", "SF Pro Display", "Helvetica Neue", Helvetica, Arial, sans-serif';

function CaseStudySideNav({ sections = [] }) {
  const [activeId, setActiveId] = useState(sections[0]?.id || "");
  const stackRef = useRef(null);
  const btnRefs = useRef([]);
  const [marker, setMarker] = useState({ top: 0, height: 0, opacity: 0 });

  useEffect(() => {
    btnRefs.current = btnRefs.current.slice(0, sections.length);
  }, [sections.length]);

  useEffect(() => {
    if (!sections.length) return;

    const scrollOffset = () =>
      window.matchMedia("(max-width: 1199px)").matches ? 136 : 108;

    let ticking = false;
    const updateActive = () => {
      const line = scrollOffset();
      let id = sections[0].id;
      for (let i = 0; i < sections.length; i++) {
        const el = document.getElementById(sections[i].id);
        if (!el) continue;
        const top = el.getBoundingClientRect().top;
        if (top <= line) id = sections[i].id;
      }
      setActiveId(id);
    };

    const onScroll = () => {
      if (ticking) return;
      ticking = true;
      requestAnimationFrame(() => {
        ticking = false;
        updateActive();
      });
    };

    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll, { passive: true });
    updateActive();

    return () => {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
    };
  }, [sections]);

  const updateMarkerPosition = useCallback(() => {
    if (typeof window === "undefined" || !window.matchMedia("(min-width: 1200px)").matches) {
      setMarker((m) => ({ ...m, opacity: 0 }));
      return;
    }
    const stack = stackRef.current;
    const idx = Math.max(0, sections.findIndex((s) => s.id === activeId));
    const btn = btnRefs.current[idx];
    if (!stack || !btn) {
      setMarker({ top: 0, height: 0, opacity: 0 });
      return;
    }
    setMarker({
      top: btn.offsetTop,
      height: btn.offsetHeight,
      opacity: 1,
    });
  }, [activeId, sections]);

  useLayoutEffect(() => {
    updateMarkerPosition();
  }, [updateMarkerPosition]);

  useEffect(() => {
    const mq = window.matchMedia("(min-width: 1200px)");
    const onResize = () => updateMarkerPosition();
    mq.addEventListener("change", onResize);
    window.addEventListener("resize", onResize, { passive: true });
    return () => {
      mq.removeEventListener("change", onResize);
      window.removeEventListener("resize", onResize);
    };
  }, [updateMarkerPosition]);

  const scrollTo = (id) => {
    const el = document.getElementById(id);
    if (!el) return;
    const offset = window.matchMedia("(max-width: 1199px)").matches ? 136 : 108;
    const top = el.getBoundingClientRect().top + window.scrollY - offset;
    window.scrollTo({ top: Math.max(0, top), behavior: "smooth" });
  };

  return (
    <React.Fragment>
      <style>{`
        .case-study-nav-wrap {
          position: relative;
          top: auto;
          z-index: 900;
          align-self: start;
          width: 100%;
          max-width: 238px;
        }
        .case-study-sidenav {
          width: 100%;
          max-height: calc(100vh - 64px);
          overflow-x: hidden;
          overflow-y: auto;
          display: flex;
          flex-direction: column;
          padding: 6px 0 20px;
          border-radius: 0;
          background: transparent;
          border: none;
          box-shadow: none;
          backdrop-filter: none;
          -webkit-backdrop-filter: none;
        }
        .case-study-sidenav-kicker {
          font-family: ${SF};
          font-size: var(--ds-text-eyebrow, 11px);
          font-weight: 600;
          letter-spacing: 0.14em;
          text-transform: uppercase;
          color: #aeaeb2;
          margin: 0 0 18px 2px;
          display: block;
        }
        .sidenav-stack {
          position: relative;
          padding-left: 14px;
        }
        .sidenav-stack::before {
          content: "";
          position: absolute;
          left: 0;
          top: 0;
          bottom: 0;
          width: 1px;
          background: rgba(210, 210, 215, 0.95);
          border-radius: 1px;
          pointer-events: none;
        }
        .sidenav-marker {
          position: absolute;
          left: 0;
          width: 2px;
          margin-left: -0.5px;
          border-radius: 2px;
          background: #1d1d1f;
          pointer-events: none;
          top: 0;
          height: 0;
          opacity: 0;
          transition:
            transform 0.45s cubic-bezier(0.25, 0.1, 0.25, 1),
            height 0.45s cubic-bezier(0.25, 0.1, 0.25, 1),
            opacity 0.25s ease;
          transform: translateY(0);
          will-change: transform, height;
        }
        .sidenav-group-label {
          font-family: ${SF};
          font-size: var(--ds-text-eyebrow, 11px);
          font-weight: 600;
          letter-spacing: 0.12em;
          text-transform: uppercase;
          color: #aeaeb2;
          margin: 18px 0 8px 2px;
        }
        .sidenav-marker + .sidenav-group-label {
          margin-top: 0;
        }
        .sidenav-btn {
          display: flex;
          align-items: center;
          gap: 10px;
          padding: 7px 8px 7px 6px;
          position: relative;
          border: none;
          border-radius: 6px;
          cursor: pointer;
          text-align: left;
          margin-bottom: 1px;
          transition: color 0.22s ease, background 0.22s ease;
          background: transparent;
          width: 100%;
          box-sizing: border-box;
        }
        .sidenav-btn:hover {
          background: rgba(0, 0, 0, 0.03);
        }
        .sidenav-btn--active {
          background: transparent;
        }
        .sidenav-btn:focus-visible {
          outline: 2px solid ${FOREST};
          outline-offset: 2px;
          border-radius: 6px;
        }
        .sidenav-btn__icon {
          flex-shrink: 0;
          display: flex;
          transition: color 0.2s ease;
          color: #c7c7cc;
        }
        .sidenav-btn--active .sidenav-btn__icon {
          color: ${FOREST};
        }
        .sidenav-btn__label {
          font-family: ${SF};
          font-size: var(--ds-text-caption, 14px);
          font-weight: 500;
          letter-spacing: -0.016em;
          color: #6e6e73;
          line-height: 1.3;
          transition: color 0.22s ease, font-weight 0.22s ease;
        }
        .sidenav-btn--active .sidenav-btn__label {
          font-weight: 600;
          color: #1d1d1f;
        }
        @media (max-width: 1199px) {
          .case-study-nav-wrap {
            max-width: none;
            top: var(--ds-nav-offset);
            margin-left: -28px;
            margin-right: -28px;
            width: calc(100% + 56px);
            padding: 10px 28px 12px;
            margin-bottom: 4px;
            background: rgba(255, 255, 255, 0.78);
            border-bottom: 1px solid rgba(210, 210, 215, 0.75);
            backdrop-filter: blur(20px) saturate(180%);
            -webkit-backdrop-filter: blur(20px) saturate(180%);
          }
          .case-study-sidenav {
            flex-direction: row;
            flex-wrap: nowrap;
            width: 100%;
            max-width: none;
            max-height: none;
            overflow-x: auto;
            overflow-y: hidden;
            padding: 8px 6px;
            gap: 4px;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: thin;
          }
          .case-study-sidenav-kicker {
            display: none;
          }
          .sidenav-stack {
            display: flex;
            flex-direction: row;
            flex-wrap: nowrap;
            gap: 4px;
            padding-left: 0;
          }
          .sidenav-stack::before,
          .sidenav-marker {
            display: none;
          }
          .sidenav-group-label {
            display: none;
          }
          .sidenav-btn {
            flex: 0 0 auto;
            width: auto;
            padding: 8px 14px;
            margin-bottom: 0;
            white-space: nowrap;
            border-radius: 100px;
          }
          .sidenav-btn__icon {
            display: flex;
          }
          .sidenav-btn--active {
            background: rgba(0, 0, 0, 0.06);
          }
          .sidenav-btn--active .sidenav-btn__label {
            font-weight: 600;
          }
        }
        @media (max-width: 768px) {
          .case-study-nav-wrap {
            margin-left: -18px;
            margin-right: -18px;
            width: calc(100% + 36px);
            padding-left: 18px;
            padding-right: 18px;
          }
        }
        @media (prefers-reduced-motion: reduce) {
          .sidenav-marker {
            transition: none;
          }
        }
      `}</style>
      <div className="case-study-nav-wrap">
        <nav className="case-study-sidenav" aria-label="Case study contents">
          <span className="case-study-sidenav-kicker">Contents</span>
          <div className="sidenav-stack" ref={stackRef}>
            <div
              className="sidenav-marker"
              style={{
                transform: `translateY(${marker.top}px)`,
                height: marker.height ? `${marker.height}px` : 0,
                opacity: marker.opacity,
              }}
              aria-hidden="true"
            />
            {sections.map((section, i) => {
              const prev = sections[i - 1];
              const showGroup = section.group && section.group !== prev?.group;
              const active = section.id === activeId;
              return (
                <Fragment key={section.id}>
                  {showGroup ? (
                    <div className="sidenav-group-label">{section.group}</div>
                  ) : null}
                  <button
                    type="button"
                    className={"sidenav-btn" + (active ? " sidenav-btn--active" : "")}
                    ref={(el) => {
                      btnRefs.current[i] = el;
                    }}
                    onClick={() => scrollTo(section.id)}
                    aria-current={active ? "location" : undefined}
                  >
                    <span className="sidenav-btn__icon" aria-hidden="true">
                      {ICONS[section.icon] || ICONS.book}
                    </span>
                    <span className="sidenav-btn__label">{section.label}</span>
                  </button>
                </Fragment>
              );
            })}
          </div>
        </nav>
      </div>
    </React.Fragment>
  );
}

const NIMBUS_SECTIONS = [
  { id: "problem", label: "The Problem", icon: "book" },
  { id: "what-i-did", label: "What I Did", icon: "sparkle" },
  { id: "usability-testing", label: "Usability Testing", icon: "flask" },
  { id: "impact", label: "Impact", icon: "trending" },
];

const PENNI_SECTIONS = [
  { id: "what-i-owned", label: "What I owned", icon: "edit", group: "Foundations" },
  { id: "context", label: "Context", icon: "book", group: "Foundations" },
  { id: "study-design", label: "Study plan", icon: "layers", group: "Plan" },
  { id: "research", label: "Research", icon: "search", group: "Plan" },
  { id: "final-designs", label: "Prototype", icon: "sparkle", group: "Design" },
  { id: "curriculum", label: "Curriculum", icon: "edit", group: "Design" },
  { id: "usability-testing", label: "RITE", icon: "flask", group: "Validation" },
  { id: "impact", label: "Impact", icon: "trending", group: "Outcomes" },
  { id: "reflection", label: "Reflection", icon: "check-circle", group: "Outcomes" },
];

const GRAB_A_SEAT_SECTIONS = [
  { id: "what-i-did", label: "What I did", icon: "lightbulb", group: "Foundations" },
  { id: "context", label: "Context", icon: "book", group: "Foundations" },
  { id: "research", label: "Research", icon: "search", group: "Foundations" },
  { id: "why-a-game", label: "Why a game", icon: "chat", group: "Strategy" },
  { id: "the-game", label: "The game", icon: "sparkle", group: "Design" },
  { id: "card-families", label: "Card families", icon: "layers", group: "Design" },
  { id: "content", label: "Content", icon: "edit", group: "Design" },
  { id: "playtesting", label: "Playtesting", icon: "flask", group: "Validation" },
  { id: "scale", label: "Scale", icon: "scale", group: "Outcomes" },
  { id: "reflection", label: "Reflection", icon: "check-circle", group: "Outcomes" },
];

const GOOGLE_MAPS_SECTIONS = [
  { id: "context", label: "Context", icon: "book", group: "Context" },
  { id: "final-designs", label: "Final Designs", icon: "sparkle", group: "Product" },
  { id: "research", label: "Research", icon: "search", group: "Product" },
  { id: "ai-integration", label: "AI Integration", icon: "lightbulb", group: "Product" },
  { id: "usability-testing", label: "Usability Testing", icon: "flask", group: "Product" },
  { id: "impact", label: "Impact", icon: "trending", group: "Outcomes" },
  { id: "reflection", label: "Reflection", icon: "check-circle", group: "Outcomes" },
];

Object.assign(window, {
  CaseStudySideNav,
  NIMBUS_SECTIONS, PENNI_SECTIONS,
  GRAB_A_SEAT_SECTIONS, GOOGLE_MAPS_SECTIONS,
});
