/* Portfolio UI kit — app shell + router */

function Footer({ t }) {
  return (
    <footer className="hu-footer">
      <span className="hu-footer__meta">{t.footMeta(new Date().getFullYear())}</span>
    </footer>
  );
}

function App() {
  const [screen, setScreen] = React.useState("home");
  const [navNonce, setNavNonce] = React.useState(0);
  const [lang, setLang] = React.useState("tw");
  const [lightboxId, setLightboxId] = React.useState(null);
  const [lbList, setLbList] = React.useState(null);
  const works = window.HU_DATA.works;
  const t = window.HU_I18N[lang];

  const go = (s) => { setScreen(s); setNavNonce((n) => n + 1); window.dispatchEvent(new Event("hu:nav")); window.scrollTo({ top: 0 }); };
  const openWork = (id, list) => { setLbList(list && list.length ? list : null); setLightboxId(id); };
  const lbWorks = () => (lbList ? lbList.map((id) => works.find((w) => w.id === id)).filter(Boolean) : works);
  const yearSetterRef = React.useRef(null);
  const [lastWorkId, setLastWorkId] = React.useState(null);
  const closeWork = () => {
    const id = lightboxId;
    const w = works.find((x) => x.id === id);
    setLightboxId(null);
    setLastWorkId(id);
    if (!id || screen === "home") return;
    requestAnimationFrame(() => {
      let el = document.getElementById(`work-${id}`);
      if (!el && w && yearSetterRef.current) {
        yearSetterRef.current(String(w.year));
        requestAnimationFrame(() => {
          el = document.getElementById(`work-${id}`);
          if (el) el.scrollIntoView({ behavior: "auto", block: "center" });
        });
      } else if (el) {
        el.scrollIntoView({ behavior: "auto", block: "center" });
      }
    });
  };
  const step = (d) => {
    const arr = lbWorks();
    const i = arr.findIndex((w) => w.id === lightboxId);
    const n = (i + d + arr.length) % arr.length;
    setLightboxId(arr[n].id);
  };

  // publish the real header height so the full-bleed hero can fill exactly one screen
  React.useLayoutEffect(() => {
    const sync = () => {
      const h = document.querySelector(".hu-hdr");
      if (!h) return;
      // phones: the bar is gone and the icon floats, so the hero gets the whole screen
      const floating = getComputedStyle(h).position === "fixed";
      document.documentElement.style.setProperty("--hdr-h", floating ? "0px" : h.getBoundingClientRect().height + "px");
    };
    sync();
    window.addEventListener("resize", sync);
    return () => window.removeEventListener("resize", sync);
  }, []);
  React.useEffect(() => { if (window.lucide) window.lucide.createIcons(); });
  // wheel scrolling: ease the jump between mouse-wheel notches (trackpads already glide, and are left alone)
  React.useEffect(() => {
    if (window.matchMedia("(pointer: coarse)").matches) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    let target = window.scrollY, raf = 0, active = false, expect = -1;
    const max = () => document.documentElement.scrollHeight - window.innerHeight;
    const stop = () => { active = false; expect = -1; if (raf) { cancelAnimationFrame(raf); raf = 0; } };
    const step = () => {
      const cur = window.scrollY;
      // someone else moved the page (navigation, anchor, keyboard) — let go of it
      if (expect >= 0 && Math.abs(cur - expect) > 4) { stop(); return; }
      const d = target - cur;
      if (Math.abs(d) < 0.4) { window.scrollTo(0, target); stop(); return; }
      const next = cur + d * 0.19;
      window.scrollTo(0, next);
      expect = window.scrollY;
      raf = requestAnimationFrame(step);
    };
    const onWheel = (e) => {
      if (e.ctrlKey || e.defaultPrevented) return;
      if (document.querySelector(".hu-lb")) return;
      // let an open menu (or any inner scroller) handle its own wheel
      if (e.target && e.target.closest && e.target.closest(".hu-selectmenu, .hu-strip, [data-scroller]")) return;
      if (e.deltaMode === 0 && Math.abs(e.deltaY) < 16) return;
      e.preventDefault();
      if (!active) { target = window.scrollY; active = true; expect = -1; }
      target = Math.max(0, Math.min(max(), target + e.deltaY * (e.deltaMode === 1 ? 16 : 1)));
      if (!raf) raf = requestAnimationFrame(step);
    };
    window.addEventListener("wheel", onWheel, { passive: false });
    window.addEventListener("hu:nav", stop);
    return () => { window.removeEventListener("wheel", onWheel); window.removeEventListener("hu:nav", stop); cancelAnimationFrame(raf); };
  }, []);
  // protect the artwork: no context menu, no drag-out, no long-press save
  React.useEffect(() => {
    const noMenu = (e) => e.preventDefault();
    const noDrag = (e) => { if (e.target.tagName === "IMG") e.preventDefault(); };
    document.addEventListener("contextmenu", noMenu);
    document.addEventListener("dragstart", noDrag);
    return () => { document.removeEventListener("contextmenu", noMenu); document.removeEventListener("dragstart", noDrag); };
  }, []);

  return (
    <div className="hu-app">
      <HUSiteHeader active={screen === "home" ? "" : screen} onNavigate={go}
        lang={lang} onLang={setLang} navItems={t.nav} variant="bordered" hideBrand={screen === "home"} />

      {screen === "home" && <window.HomeScreen t={t} lang={lang} go={go} openWork={openWork} lastWorkId={lastWorkId} />}
      {screen === "works" && <window.WorksScreen t={t} lang={lang} openWork={openWork} registerYearSetter={(fn) => { yearSetterRef.current = fn; }} />}
      {screen === "profile" && <window.ProfileScreen t={t} lang={lang} />}
      {screen === "writings" && <window.WritingsScreen key={navNonce} t={t} lang={lang} />}
      {screen === "information" && <window.InformationScreen t={t} lang={lang} openWork={openWork} />}

      <Footer t={t} />

      {lightboxId && (
        <window.Lightbox work={works.find((w) => w.id === lightboxId)} lang={lang} list={lbWorks()}
          onClose={closeWork} onPrev={() => step(-1)} onNext={() => step(1)} />
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
