// shared.jsx — hooks, helpers, Nav, Footer
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// ───────── hooks ─────────

function useLocalState(key, init) {
  const [v, setV] = useState(() => {
    try {
      const raw = localStorage.getItem(key);
      if (raw != null) return JSON.parse(raw);
    } catch (e) {}
    return init;
  });
  useEffect(() => {
    try { localStorage.setItem(key, JSON.stringify(v)); } catch (e) {}
  }, [key, v]);
  return [v, setV];
}

function useInView(threshold = 0.12) {
  const ref = useRef(null);
  const [seen, setSeen] = useState(false);
  useEffect(() => {
    if (!ref.current || seen) return;
    const io = new IntersectionObserver(
      (ents) => ents.forEach((e) => {
        if (e.isIntersecting) { setSeen(true); io.disconnect(); }
      }),
      { threshold }
    );
    io.observe(ref.current);
    return () => io.disconnect();
  }, [seen, threshold]);
  return [ref, seen];
}

function normalizeHash(h) {
  const s = (h || "").replace(/^#\/?/, "").replace(/\/$/, "");
  return s || "home";
}

// Page routes are "", "#", "#/", "#/foo", "#/foo/bar".
// Anchor jumps like "#credo" or "#education" stay on the same page —
// don't reset scroll, let the browser handle the anchor.
function isPageRouteHash(hash) {
  return !hash || hash === "#" || hash.startsWith("#/");
}

function useRoute() {
  const [route, setRoute] = useState(() => normalizeHash(window.location.hash));
  useEffect(() => {
    const onHash = () => {
      const hash = window.location.hash;
      if (!isPageRouteHash(hash)) return;
      setRoute(normalizeHash(hash));
      // Skip scroll-to-top if a section jump is pending — the App effect
      // will scrollIntoView the right element instead, avoiding a flash.
      let pending = null;
      try { pending = sessionStorage.getItem("nv:scrollAfterRoute"); } catch (e) {}
      if (!pending) window.scrollTo({ top: 0, behavior: "auto" });
    };
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);
  return route;
}

// ───────── Logo monogram (NV touching) ─────────

function Monogram({ size = 28 }) {
  return (
    <svg
      viewBox="0 0 60 42"
      height={size}
      width={size * 1.4}
      className="monogram"
      preserveAspectRatio="xMidYMid meet"
      aria-hidden="true"
    >
      <text x="0" y="34" className="mono-n">N</text>
      <text x="14" y="34" className="mono-v">V</text>
    </svg>
  );
}

// ───────── Nav ─────────

// Click handler for nav links that point at a section on the home page
// (credo / education / projects / connect). If we're already on home,
// let the browser do the native anchor scroll. Otherwise navigate to
// home and stash the target so the App effect can scroll to it after
// HomePage mounts.
function jumpToHomeSection(e, sectionId, route) {
  if (route === "home") return; // native scroll handles it
  e.preventDefault();
  try { sessionStorage.setItem("nv:scrollAfterRoute", sectionId); } catch (err) {}
  if (window.location.hash === "#/" || window.location.hash === "") {
    // Already at the home URL but route somehow isn't "home" — just scroll.
    const el = document.getElementById(sectionId);
    if (el) el.scrollIntoView({ behavior: "auto", block: "start" });
  } else {
    window.location.hash = "#/";
  }
}

function Nav({ t, lang, setLang, theme, setTheme, route }) {
  const [langOpen, setLangOpen] = useState(false);
  const [scrolled, setScrolled] = useState(false);
  const [menuOpen, setMenuOpen] = useState(false);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 32);
    onScroll();
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  // Close the mobile menu whenever the route changes (page navigation).
  useEffect(() => { setMenuOpen(false); }, [route]);

  // Lock body scroll while the mobile menu is open so the page behind
  // doesn't scroll under the user's finger.
  useEffect(() => {
    if (!menuOpen) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => { document.body.style.overflow = prev; };
  }, [menuOpen]);

  const LANGS = ["ru", "en", "es"];
  const isHome = route === "home";

  // The 5 nav items — rendered in both the desktop nav-links row and
  // the mobile menu overlay so click behavior stays in one place.
  const navItems = [
    { href: "#credo", label: t.quote.kicker, section: "credo" },
    { href: "#education", label: t.nav.studies, section: "education" },
    { href: "#projects", label: t.nav.projects, section: "projects" },
    { href: "#/videos", label: t.nav.videos, section: null },
    { href: "#connect", label: t.nav.connect, section: "connect" },
  ];

  const onItemClick = (e, section) => {
    if (section) jumpToHomeSection(e, section, route);
    setMenuOpen(false);
  };

  return (
    <>
    <header className={"nav " + (scrolled || !isHome ? "is-scrolled" : "")}>
      <a className="nav-mark" href="#/" aria-label="Natalia Vointseva — home">
        <Monogram size={26} />
      </a>

      <nav className="nav-links" aria-label="Sections">
        {navItems.map((it) => (
          <a key={it.href} href={it.href} onClick={(e) => onItemClick(e, it.section)}>
            {it.label}
          </a>
        ))}
      </nav>

      <div className="nav-controls">
        <div className={"lang " + (langOpen ? "is-open" : "")}>
          <button
            className="lang-btn"
            onClick={() => setLangOpen((o) => !o)}
            onBlur={() => setTimeout(() => setLangOpen(false), 120)}
            aria-haspopup="listbox"
            aria-expanded={langOpen}
            aria-label={t.ui.switchLang}
          >
            <span className="lang-current">{lang.toUpperCase()}</span>
            <svg width="9" height="6" viewBox="0 0 9 6" aria-hidden="true">
              <path d="M1 1l3.5 4L8 1" stroke="currentColor" strokeWidth="1.2" fill="none" strokeLinecap="round" />
            </svg>
          </button>
          <ul className="lang-menu" role="listbox">
            {LANGS.map((code) => (
              <li key={code}>
                <button
                  className={code === lang ? "is-active" : ""}
                  onClick={() => { setLang(code); setLangOpen(false); }}
                >
                  <span className="lang-code">{code.toUpperCase()}</span>
                  <span className="lang-full">{window.I18N[code].full}</span>
                </button>
              </li>
            ))}
          </ul>
        </div>

        <button
          className="theme-toggle"
          onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
          aria-label={t.ui.switchTheme}
          title={t.ui.switchTheme}
        >
          <span className="theme-icon">
            <svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true">
              <path d="M12 3.5v2M12 18.5v2M5.5 12h-2M20.5 12h-2M7.05 7.05L5.64 5.64M18.36 18.36l-1.41-1.41M16.95 7.05l1.41-1.41M5.64 18.36l1.41-1.41" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" fill="none" />
              <circle cx="12" cy="12" r="3.6" stroke="currentColor" strokeWidth="1.3" fill="none" />
            </svg>
            <svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true">
              <path d="M19.5 14.5a8 8 0 0 1-10-10 8 8 0 1 0 10 10z" stroke="currentColor" strokeWidth="1.3" fill="none" strokeLinejoin="round" />
            </svg>
          </span>
          <span className="theme-label">{theme === "dark" ? t.ui.themeDark : t.ui.themeLight}</span>
        </button>

        <button
          className={"nav-burger " + (menuOpen ? "is-open" : "")}
          onClick={() => setMenuOpen((o) => !o)}
          aria-label={menuOpen ? "Close menu" : "Open menu"}
          aria-expanded={menuOpen}
          aria-controls="nv-mobile-menu"
        >
          <span className="nav-burger-bar" />
          <span className="nav-burger-bar" />
          <span className="nav-burger-bar" />
        </button>
      </div>
    </header>

    <div
      id="nv-mobile-menu"
      className="nav-menu-overlay"
      data-open={menuOpen}
      onClick={() => setMenuOpen(false)}
      aria-hidden={!menuOpen}
    >
      <nav
        className="nav-menu"
        aria-label="Mobile navigation"
        onClick={(e) => e.stopPropagation()}
      >
        {navItems.map((it) => (
          <a key={it.href} href={it.href} onClick={(e) => onItemClick(e, it.section)}>
            {it.label}
          </a>
        ))}
      </nav>
    </div>
    </>
  );
}

// ───────── Footer ─────────

function Footer({ t }) {
  return (
    <footer className="foot">
      <div className="foot-rule" />
      <div className="foot-grid">
        <div className="foot-mark">
          <Monogram size={32} />
          <div className="foot-mark-meta">
            <span className="foot-mark-name">Natalia Vointseva</span>
            <span className="foot-mark-loc">{t.hero.eyebrow}</span>
          </div>
        </div>
        <p className="foot-rights">{t.footer.rights}</p>
        <p className="foot-colophon">{t.footer.colophon}</p>
      </div>
    </footer>
  );
}

// ───────── Kicker ─────────

function Kicker({ children }) {
  return (
    <div className="section-kicker">
      <span className="section-rule" />
      <span>{children}</span>
    </div>
  );
}

// ───────── SectionTitle (multi-line, italicized 2nd line) ─────────

function SectionTitle({ text }) {
  const lines = text.split("\n");
  return (
    <h2 className="section-title">
      {lines.map((line, i) => (
        <span
          key={i}
          className={
            "section-title-line " +
            (i === 1 ? "section-title-line--italic " : "") +
            (i === 2 ? "section-title-line--indent " : "")
          }
        >
          {line}
        </span>
      ))}
    </h2>
  );
}

// Expose to other Babel scripts
Object.assign(window, {
  useLocalState, useInView, useRoute, normalizeHash,
  Monogram, Nav, Footer, Kicker, SectionTitle,
});
