const { useState: useStateApp, useEffect: useEffectApp, useRef: useRefApp, useLayoutEffect: useLayoutEffectApp } = React;

function App() {
  const [route, setRoute] = useStateApp({ name: "feed" });
  const [, setPostsVersion] = useStateApp(0);
  const [lightboxPost, setLightboxPost] = useStateApp(null);
  const feedRefs = useRefApp({});
  const heroRef = useRefApp(null);
  const scrollY = useRefApp(0);
  const pendingFlip = useRefApp(null);

  useEffectApp(() => {
    const params = new URLSearchParams(window.location.search);
    const isPreview = params.get("preview") === "1";

    if (isPreview) {
      const handle = (event) => {
        const data = event.data;
        if (!data || data.type !== "kpjournal:preview" || !data.post) return;
        const post = data.post;
        window.POSTS = [post];
        setPostsVersion((n) => n + 1);
        if (data.view === "post" && post.long) {
          setRoute({ name: "post", post });
        } else {
          setRoute({ name: "feed" });
        }
      };
      window.addEventListener("message", handle);
      try { window.parent && window.parent.postMessage({ type: "kpjournal:ready" }, "*"); } catch (_) {}
      return () => window.removeEventListener("message", handle);
    }

    let cancelled = false;
    fetch("/api/posts")
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error("api"))))
      .then(({ posts }) => {
        if (cancelled || !Array.isArray(posts)) return;
        window.POSTS = posts;
        setPostsVersion((n) => n + 1);
      })
      .catch(() => { /* keep window.POSTS from data.js fallback */ });
    return () => { cancelled = true; };
  }, []);

  const openPost = (post) => {
    if (post.long) {
      const el = feedRefs.current[post.id];
      const rect = el ? el.getBoundingClientRect() : null;
      scrollY.current = window.scrollY;
      pendingFlip.current = { fromRect: rect, postId: post.id };
      setRoute({ name: "post", post });
      return;
    }
    if (post.kind !== "link" && post.hero_r2_key) {
      setLightboxPost(post);
    }
  };

  const backToFeed = () => {
    setRoute({ name: "feed" });
    requestAnimationFrame(() => window.scrollTo(0, scrollY.current));
  };

  useLayoutEffectApp(() => {
    if (route.name !== "post") return;
    const p = pendingFlip.current;
    pendingFlip.current = null;
    if (!p || !p.fromRect || !heroRef.current) return;

    const hero = heroRef.current;
    window.scrollTo(0, 0);
    const heroRect = hero.getBoundingClientRect();
    const from = p.fromRect;

    const dx = from.left - heroRect.left;
    const dy = from.top - heroRect.top;
    const sx = from.width / heroRect.width;
    const sy = from.height / heroRect.height;

    hero.style.transformOrigin = "top left";
    hero.style.transform = `translate(${dx}px, ${dy}px) scale(${sx}, ${sy})`;
    hero.style.transition = "none";
    hero.style.opacity = "1";

    hero.offsetHeight;
    hero.style.transition = "transform 560ms cubic-bezier(0.22, 0.61, 0.36, 1)";
    hero.style.transform = "translate(0,0) scale(1,1)";

    const post = document.querySelector(".post");
    if (post) {
      post.classList.add("post-entering");
      requestAnimationFrame(() => post.classList.add("post-entered"));
    }

    const clean = () => { hero.style.transition = ""; hero.style.transform = ""; };
    setTimeout(clean, 620);
  }, [route.name]);

  const onNav = (name, extra) => {
    setRoute({ name, ...(extra || {}) });
    window.scrollTo(0, 0);
  };

  return (
    <div className="app" data-route={route.name}>
      {route.name === "post" ? null : <Masthead onNav={onNav} current={route.name} />}

      {route.name === "feed" && (
        <Feed
          onOpen={openPost}
          refs={feedRefs}
          seriesFilter={route.series}
          onClearFilter={() => onNav("feed")}
          onOpenSeries={(name) => onNav("feed", { series: name })}
        />
      )}
      {route.name === "post" && <PostView post={route.post} heroRef={heroRef} onBack={backToFeed} />}
      {route.name === "about" && <About />}
      {route.name === "series" && <Series onOpenSeries={(name) => onNav("feed", { series: name })} />}
      {route.name === "gear" && <Gear />}
      {route.name === "contact" && <Contact />}

      {route.name !== "post" && <Footer />}

      {lightboxPost && (
        <Lightbox post={lightboxPost} onClose={() => setLightboxPost(null)} />
      )}
    </div>
  );
}

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