/* ============================================================
   Portfolio: root: glass nav, theme toggle, section composition
   ============================================================ */
const RESUME_URL = "assets/Genevieve_Liu_Resume.pdf";

/* Each nav item can carry a peek menu: a few real destinations, so the bar
   previews the page instead of just scrolling to it. */
const NAV = [
  { id: "home", label: "Home" },
  {
    id: "about", label: "About",
    menu: [
      { t: "Senior Product Designer", d: "Dentsu × Subaru of America", to: "about" },
      { t: "ZeyaAI", d: "Self-directed AI practice · nomi, Nyla", href: "https://zeyaai.com" },
      { t: "Résumé", d: "PDF · one page", href: RESUME_URL, blank: true },
    ],
  },
  {
    id: "work", label: "Work",
    menu: [
      { t: "nomi", d: "Social-self generator · live", case: "nomi" },
      { t: "NYLA", d: "AI-native identity system", case: "nyla" },
      { t: "MySubaru Redesign", d: "2M+ connected owners", case: "mysubaru-redesign" },
      { t: "MySubaru Onboarding", d: "Purchase to activation", case: "mysubaru-onboarding" },
      { t: "AI Driving Assistant", d: "Calibrated proactivity", case: "subaru-agentic-ai" },
    ],
  },
  {
    id: "contact", label: "Contact",
    menu: [
      { t: "vi.vignette@gmail.com", d: "Email me", href: "mailto:vi.vignette@gmail.com" },
      { t: "LinkedIn", d: "Let's connect", href: "https://www.linkedin.com/in/genevieveliu/", blank: true },
      { t: "Résumé", d: "PDF · one page", href: RESUME_URL, blank: true },
    ],
  },
];

function useTheme() {
  const [theme, setTheme] = useState(function () {
    return document.documentElement.getAttribute("data-theme") || "dark";
  });
  const toggle = useCallback(function () {
    setTheme(function (t) {
      const next = t === "dark" ? "light" : "dark";
      document.documentElement.setAttribute("data-theme", next);
      try { localStorage.setItem("gv-theme", next); } catch (e) {}
      return next;
    });
  }, []);
  return [theme, toggle];
}

/* Scroll to a section, accounting for the fixed nav (no scrollIntoView). */
function scrollToId(id) {
  const el = document.getElementById(id);
  if (!el) return;
  const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
  const top = el.getBoundingClientRect().top + window.scrollY - (id === "home" ? 0 : 84);
  window.scrollTo({ top: top, behavior: reduced ? "auto" : "smooth" });
}

function useActiveSection() {
  const [active, setActive] = useState("home");
  const lock = useRef(0);
  useEffect(function () {
    function onScroll() {
      if (Date.now() < lock.current) return; // honour a recent click
      const ids = NAV.map(function (n) { return n.id; });
      const mid = window.scrollY + window.innerHeight * 0.4;
      let current = "home";
      let bestTop = -Infinity;
      ids.forEach(function (id) {
        const el = document.getElementById(id);
        if (el && el.offsetTop <= mid && el.offsetTop > bestTop) {
          bestTop = el.offsetTop;
          current = id;
        }
      });
      // near the bottom of a real (laid-out, scrollable) page, force the last section
      if (window.scrollY > 0 && document.body.scrollHeight > window.innerHeight * 1.5 &&
          window.innerHeight + window.scrollY >= document.body.scrollHeight - 4) {
        current = ids[ids.length - 1];
      }
      setActive(current);
    }
    onScroll();
    // re-run after layout settles (fonts, reveal sections, case grid)
    requestAnimationFrame(onScroll);
    window.addEventListener("load", onScroll);
    window.addEventListener("scroll", onScroll, { passive: true });
    window.addEventListener("resize", onScroll);
    return function () {
      window.removeEventListener("scroll", onScroll);
      window.removeEventListener("resize", onScroll);
      window.removeEventListener("load", onScroll);
    };
  }, []);
  const choose = useCallback(function (id) {
    setActive(id);
    lock.current = Date.now() + 900; // ignore scroll-driven updates while the smooth scroll runs
    scrollToId(id);
  }, []);
  return [active, choose];
}

/* Hover/focus peek menu under a nav item. */
function NavMenu(props) {
  const items = props.items;
  return (
    <div className="gv-navmenu pf-glass" role="menu" aria-label={props.label + " menu"}>
      {items.map(function (m, i) {
        const inner = (
          <React.Fragment>
            <span className="t">{m.t}</span>
            <span className="d">{m.d}</span>
          </React.Fragment>
        );
        const common = { key: m.t + i, className: "gv-navmenu-item", role: "menuitem", style: { transitionDelay: (i * 26) + "ms" } };
        if (m.case) {
          return <button {...common} onClick={function () { props.onCase(m.case); }}>{inner}</button>;
        }
        return (
          <a {...common} href={m.href || ("#" + m.to)}
            target={m.blank ? "_blank" : undefined} rel={m.blank ? "noopener noreferrer" : undefined}
            onClick={m.to ? function (e) { e.preventDefault(); props.onSection(m.to); } : undefined}>
            {inner}
          </a>
        );
      })}
    </div>
  );
}

function NavBar(props) {
  const { theme, toggle } = props;
  const [active, choose] = useActiveSection();
  const [open, setOpen] = useState(null);
  const closeT = useRef(0);
  function hold(id) { clearTimeout(closeT.current); setOpen(id); }
  function release() { clearTimeout(closeT.current); closeT.current = setTimeout(function () { setOpen(null); }, 160); }
  function go(id) { return function (e) { e.preventDefault(); setOpen(null); choose(id); }; }
  return (
    <header style={{
      position: "fixed", top: 0, left: 0, right: 0, zIndex: 50,
      display: "flex", alignItems: "center", justifyContent: "space-between",
      gap: 20, padding: "20px clamp(24px, 4.5vw, 72px)",
      pointerEvents: "none",
    }}>
      {/* wordmark */}
      <a href="#home" onClick={go("home")} className="gv-wordmark gv-underline" style={{
        pointerEvents: "auto", textDecoration: "none",
        fontSize: 18, fontWeight: 400, letterSpacing: "0.02em",
        color: "var(--label-primary)", height: 48, display: "inline-flex", alignItems: "center",
      }}>Genevieve</a>

      {/* center nav pill */}
      <nav aria-label="Primary" className="gv-navpill pf-glass" style={{
        pointerEvents: "auto",
        display: "flex", alignItems: "center", gap: 4, padding: 6, height: 48,
        borderRadius: 999,
      }}>
        {NAV.map(function (n) {
          const on = active === n.id;
          const isOpen = open === n.id;
          return (
            <div key={n.id} className="gv-navitem"
              onMouseEnter={n.menu ? function () { hold(n.id); } : undefined}
              onMouseLeave={n.menu ? release : undefined}
              onFocus={n.menu ? function () { hold(n.id); } : undefined}
              onBlur={n.menu ? release : undefined}>
              <a href={"#" + n.id} onClick={go(n.id)}
                aria-current={on ? "page" : undefined}
                aria-expanded={n.menu ? (isOpen ? "true" : "false") : undefined}
                className="gv-navlink"
                style={{
                  position: "relative", textDecoration: "none",
                  display: "inline-flex", alignItems: "center", height: 36,
                  padding: "0 20px", borderRadius: 999,
                  fontSize: 14, fontWeight: 400, letterSpacing: "0.01em",
                  color: on || isOpen ? "var(--label-primary)" : "var(--label-secondary)",
                  background: on ? "var(--pf-glass-tint-thick)" : "transparent",
                  border: on ? "1px solid var(--pf-border)" : "1px solid transparent",
                  boxShadow: on ? "inset 0 1px 1px rgba(255,255,255,0.35)" : "none",
                  transition: "color 220ms var(--glass-ease), background 360ms var(--glass-spring)",
                }}>
                {n.label}
              </a>
              {n.menu && isOpen ? (
                <NavMenu items={n.menu} label={n.label} onCase={props.onOpenCase} onSection={choose} />
              ) : null}
            </div>
          );
        })}
      </nav>

      {/* right cluster */}
      <div style={{ pointerEvents: "auto", display: "flex", alignItems: "center", gap: 12 }}>
        <a href={RESUME_URL} target="_blank" rel="noopener noreferrer"
          aria-label="Open résumé (PDF, opens in a new tab)"
          className="gv-resume pf-glass gv-lift" style={{
            display: "inline-flex", alignItems: "center", gap: 9,
            height: 48, padding: "0 24px", borderRadius: 999,
            textDecoration: "none", fontSize: 14, fontWeight: 400, letterSpacing: "0.01em",
            color: "var(--label-primary)",
          }}>
          Resume
          <i data-lucide="arrow-up-right" style={{ width: 15, height: 15, opacity: 0.6 }} />
        </a>
        {/* On a phone the nav pill is gone, so the header's one action leads
            into the work instead of out to a PDF. It lands on the first
            cover itself, not on the section heading above it. */}
        <button onClick={function () {
            const el = document.querySelector("#work .gv-featured") || document.getElementById("work");
            if (!el) return;
            const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
            const top = el.getBoundingClientRect().top + window.scrollY - 88;
            window.scrollTo({ top: top, behavior: reduced ? "auto" : "smooth" });
          }}
          aria-label="Jump to the work section"
          className="gv-viewwork pf-glass gv-lift" style={{
            display: "none", alignItems: "center", gap: 9,
            height: 48, padding: "0 24px", borderRadius: 999,
            cursor: "pointer", fontSize: 14, fontWeight: 400, letterSpacing: "0.01em",
            color: "var(--label-primary)",
          }}>
          View Work
          <i data-lucide="arrow-down" style={{ width: 15, height: 15, opacity: 0.6 }} />
        </button>
        <button onClick={toggle} aria-pressed={theme === "light"}
          aria-label={theme === "dark" ? "Switch to light mode" : "Switch to dark mode"}
          className="pf-glass gv-lift"
          style={{
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            width: 48, height: 48, borderRadius: 999,
            cursor: "pointer", color: "var(--label-primary)",
          }}>
          <i data-lucide="moon" style={{ width: 18, height: 18 }} />
        </button>
      </div>
    </header>
  );
}

function navClick(id) {
  return function (e) { e.preventDefault(); scrollToId(id); };
}

function Portfolio() {
  const [theme, toggle] = useTheme();
  const [activeCase, setActiveCase] = useState(null);
  const openCase = useCallback(function (id) { window.scrollTo(0, 0); setActiveCase(id); }, []);
  const navCase = useCallback(function (id) { window.scrollTo(0, 0); setActiveCase(id); }, []);
  const backHome = useCallback(function () {
    setActiveCase(null);
    setTimeout(function () { scrollToId("work"); }, 0);
  }, []);

  if (activeCase) {
    return (
      <React.Fragment>
        <PageBackground />
        <GlobalLens />
        <CaseStudy caseId={activeCase} onBack={backHome} onNav={navCase} theme={theme} toggle={toggle} />
      </React.Fragment>
    );
  }

  return (
    <React.Fragment>
      <PageBackground />
      <GlobalLens />
      <NavBar theme={theme} toggle={toggle} onOpenCase={openCase} />
      <main id="main">
        <Cover theme={theme} go={scrollToId} />
        <AboutSection />
        <WorkSection onOpen={openCase} theme={theme} />
        <ConnectSection />
        <Footer />
      </main>
    </React.Fragment>
  );
}

window.Portfolio = Portfolio;
