// =============================================================
// App — top-level shell + routing + Supabase boot gate
// =============================================================

const useIsMobile = (query = "(max-width: 720px)") => {
  const [isMobile, setIsMobile] = useState(() =>
    typeof window !== "undefined" && window.matchMedia ? window.matchMedia(query).matches : false
  );
  useEffect(() => {
    if (!window.matchMedia) return;
    const mql = window.matchMedia(query);
    const handler = (e) => setIsMobile(e.matches);
    mql.addEventListener ? mql.addEventListener("change", handler) : mql.addListener(handler);
    return () => {
      mql.removeEventListener ? mql.removeEventListener("change", handler) : mql.removeListener(handler);
    };
  }, [query]);
  return isMobile;
};

const useStored = (key, defaultVal) => {
  const [v, setV] = useState(() => {
    const cached = window.xm.store.get(key, undefined);
    return cached === undefined || cached === null ? defaultVal : cached;
  });
  useEffect(() => {
    return window.xm.store.subscribe(key, (next) => setV(next));
  }, [key]);
  const set = (next) => {
    const value = typeof next === "function" ? next(v) : next;
    setV(value);
    window.xm.store.set(key, value);
  };
  return [v, set];
};

// Loading splash — soft butter screen while we hydrate from Supabase.
const BootSplash = ({ error }) => (
  <div style={{
    position: "fixed", inset: 0,
    background: "radial-gradient(60% 50% at 50% 40%, #FFEFC9 0%, #FFF8DD 70%)",
    display: "flex", alignItems: "center", justifyContent: "center",
    flexDirection: "column", gap: 14, zIndex: 1000,
  }}>
    <img src={(window.XM_BRAND && window.XM_BRAND.logoUrl) || "../assets/app-icon.png"} style={{ width: 96, height: 96, animation: "xm-pulse-soft 1.6s ease-in-out infinite" }} alt=""/>
    <div style={{ font: "600 16px 'Jiangcheng Yuan', 'PingFang SC', sans-serif", color: "#6B4A2E", letterSpacing: "0.04em" }}>
      {error ? "连不上小宇宙了，刷新看看？" : "正在打开我们的小宇宙……"}
    </div>
    <style>{`@keyframes xm-pulse-soft { 0%,100% { transform: scale(1) } 50% { transform: scale(1.07) } }`}</style>
  </div>
);

// 退出登录：清掉本机 session，回到登录门。
const forgetPairedDevice = async () => {
  try { await window.xm.auth.signOut(); } catch (e) {}
  window.location.reload();
};

const App = () => {
  const petOn = !!(window.XM_FEATURES && window.XM_FEATURES.pet);
  const [page, setPage] = useState(() => {
    const requested = new URLSearchParams(window.location.search).get("page");
    const valid = ["home", "album", "promises", "stories"].concat(petOn ? ["pet"] : []);
    return valid.includes(requested) ? requested : "home";
  });
  const isMobile = useIsMobile();
  const [settings, setSettings] = useStored("settings", { nickname: "宝贝", myName: "我", togetherDate: window.xm.util.ymd(new Date()), anniversaries: [] });
  const [photos, setPhotos] = useStored("photos", []);
  const [promises, setPromises] = useStored("promises", []);
  const [stories, setStories] = useStored("stories", []);
  const [showSettings, setShowSettings] = useState(false);
  const [showContact, setShowContact] = useState(false);
  const [showAnniversaries, setShowAnniversaries] = useState(false);
  const [showImportantEvents, setShowImportantEvents] = useState(false);
  const [photoOpen, setPhotoOpen] = useState(null);
  const [confettiTrig, setConfettiTrig] = useState(0);
  const [toast, setToast] = useState(null);

  const fireConfetti = (text) => {
    setConfettiTrig(t => t + 1);
    if (text) {
      setToast(text);
      setTimeout(() => setToast(null), 2400);
    }
  };

  const pages = {
    home:     <HomePage settings={settings} photos={photos} promises={promises} stories={stories} onNav={setPage} onPhotoOpen={setPhotoOpen} onEditAnniversaries={() => setShowAnniversaries(true)} onEditImportantEvents={() => setShowImportantEvents(true)} onPetOpen={() => setPage("pet")}/>,
    album:    <AlbumPage photos={photos} onChange={setPhotos} settings={settings} onPhotoOpen={setPhotoOpen}/>,
    pet:      <PetDetailPage onBack={() => {
      setPage("home");
      const url = new URL(window.location.href);
      url.searchParams.delete("page");
      url.searchParams.delete("mood");
      window.history.replaceState({}, "", url.pathname + url.search + url.hash);
    }}/>,
    promises: <PromisesPage promises={promises} onChange={setPromises} onConfetti={() => fireConfetti("已经兑现啦 ✨")}/>,
    stories:  <StoriesPage stories={stories} onChange={setStories} settings={settings}/>,
  };
  const isPetPage = page === "pet";

  return (
    <div style={{ display: "flex", flexDirection: isMobile ? "column" : "row", minHeight: "100vh", position: "relative" }}>
      {!isPetPage && <FloatingMotifs/>}
      {!isMobile && !isPetPage && <Sidebar active={page} onNav={setPage} onSettings={() => setShowSettings(true)} settings={settings}/>}
      {isMobile && page === "home" && <TopBar onSettings={() => setShowSettings(true)}/>}
      <main className={`xm-main${page === "pet" ? " xm-main-pet" : ""}`} style={{ flex: 1, padding: "32px 40px 80px", maxWidth: 1180, margin: "0 auto", position: "relative", zIndex: 1, minWidth: 0, width: "100%", boxSizing: "border-box" }}>
        {pages[page]}
      </main>
      {isMobile && !isPetPage && <BottomNav active={page} onNav={setPage}/>}
      {!isMobile && !isPetPage && <ContactButton onClick={() => setShowContact(true)}/>}
      <ContactModal open={showContact} onClose={() => setShowContact(false)}/>
      <SettingsModal open={showSettings} onClose={() => setShowSettings(false)} settings={settings} onChange={setSettings} onForgetDevice={forgetPairedDevice} onContact={() => { setShowSettings(false); setShowContact(true); }}/>
      <AnniversariesModal open={showAnniversaries} onClose={() => setShowAnniversaries(false)} settings={settings} onChange={setSettings}/>
      <ImportantEventsModal open={showImportantEvents} onClose={() => setShowImportantEvents(false)} stories={stories} onChange={setStories} onNav={(p) => { setShowImportantEvents(false); setPage(p); }}/>
      <PhotoDetail photo={photoOpen} photos={photos} onClose={setPhotoOpen} onChange={setPhotos} settings={settings}/>
      <ConfettiBurst trigger={confettiTrig}/>
      {toast && <div style={{ position: "fixed", left: "50%", bottom: 40, transform: "translateX(-50%)", zIndex: 400, animation: "toastIn 280ms cubic-bezier(0.34,1.56,0.64,1)" }}>
        <Toast tone="success">{toast}</Toast>
      </div>}
      <style>{`@keyframes toastIn { from { transform: translate(-50%, 20px); opacity: 0 } to { transform: translate(-50%, 0); opacity: 1 } }`}</style>
    </div>
  );
};

// Boot gate: 先确认登录（暗号门在 index.html 里，能在 React/Babel 加载前就渲染），
// 登录确认后再 hydrate Supabase 数据。
const Root = () => {
  const [ready, setReady] = useState(false);
  const [error, setError] = useState(false);
  useEffect(() => {
    let cancelled = false;
    (async () => {
      // 已登录则直接 boot；否则等 index.html 的登录门发出 xm-authed 事件。
      const session = await window.xm.auth.currentSession();
      if (!session && !window.__xmAuthed) {
        await new Promise((resolve) => window.addEventListener("xm-authed", resolve, { once: true }));
      }
      const ok = await window.xm.start();
      if (cancelled) return;
      ok ? setReady(true) : setError(true);
    })();
    return () => { cancelled = true; };
  }, []);
  if (!ready) return <BootSplash error={error}/>;
  return <App/>;
};

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